mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-27 02:41:53 +00:00
Compare commits
68 Commits
refactor/t
...
fix/fe-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
201965b809 | ||
|
|
2baf1a880b | ||
|
|
58e0b166cb | ||
|
|
2a678bb017 | ||
|
|
5664456b77 | ||
|
|
3685b7e57e | ||
|
|
989d5f73b1 | ||
|
|
4f84073cb5 | ||
|
|
c190295c34 | ||
|
|
60875644a1 | ||
|
|
113b09ad01 | ||
|
|
2605d0e671 | ||
|
|
d232b91d31 | ||
|
|
c65db31fd9 | ||
|
|
99871805bd | ||
|
|
e8ef39adad | ||
|
|
466b9217b5 | ||
|
|
c9a7f519b9 | ||
|
|
96ae532879 | ||
|
|
eda08d5b0f | ||
|
|
7c12b58bb5 | ||
|
|
5446c89bc0 | ||
|
|
2d0251e585 | ||
|
|
f41710c892 | ||
|
|
df3f79f282 | ||
|
|
f8df692865 | ||
|
|
0c6d3b188d | ||
|
|
e7a38863ab | ||
|
|
720e0fcdab | ||
|
|
bf8ff84522 | ||
|
|
5a9510238e | ||
|
|
7b3c74179b | ||
|
|
cd70fa4c32 | ||
|
|
83133ced6a | ||
|
|
6c5179a179 | ||
|
|
e33ab39b85 | ||
|
|
9567bcec1b | ||
|
|
550b16dc0b | ||
|
|
5d8331b7f7 | ||
|
|
e35b643e51 | ||
|
|
bc6a92677b | ||
|
|
f52072e6ec | ||
|
|
9c43c43a46 | ||
|
|
0430e0f930 | ||
|
|
b945243d1a | ||
|
|
d8484a8b26 | ||
|
|
3c27499795 | ||
|
|
7c772e873d | ||
|
|
db2fab245e | ||
|
|
a9c9917f1a | ||
|
|
23e2e9e9cc | ||
|
|
2369e92460 | ||
|
|
a53b15f2a3 | ||
|
|
72eb8b1eb6 | ||
|
|
4db54f3b83 | ||
|
|
24eb27f005 | ||
|
|
009d76ea35 | ||
|
|
6e8a425eb1 | ||
|
|
66188d791b | ||
|
|
015ff02d71 | ||
|
|
10bfaf5415 | ||
|
|
e3e0b85e0c | ||
|
|
ad0632892e | ||
|
|
f26791ba39 | ||
|
|
2fbaaebf44 | ||
|
|
edb916338c | ||
|
|
f7e947d37d | ||
|
|
a9e3d1ed75 |
81
.github/actions/setup-build/action.yml
vendored
Normal file
81
.github/actions/setup-build/action.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
name: Setup Build Environment
|
||||||
|
description: Common build environment setup steps
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
nodejs-version:
|
||||||
|
description: Node.js version
|
||||||
|
required: true
|
||||||
|
setup-python:
|
||||||
|
description: Set up Python
|
||||||
|
required: false
|
||||||
|
default: "false"
|
||||||
|
setup-docker:
|
||||||
|
description: Set up Docker QEMU and Buildx
|
||||||
|
required: false
|
||||||
|
default: "true"
|
||||||
|
setup-sccache:
|
||||||
|
description: Configure sccache for GitHub Actions
|
||||||
|
required: false
|
||||||
|
default: "true"
|
||||||
|
free-space:
|
||||||
|
description: Remove unnecessary packages to free disk space
|
||||||
|
required: false
|
||||||
|
default: "true"
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Free disk space
|
||||||
|
if: inputs.free-space == 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get remove --purge -y azure-cli || true
|
||||||
|
sudo apt-get remove --purge -y firefox || true
|
||||||
|
sudo apt-get remove --purge -y ghc-* || true
|
||||||
|
sudo apt-get remove --purge -y google-cloud-sdk || true
|
||||||
|
sudo apt-get remove --purge -y google-chrome-stable || true
|
||||||
|
sudo apt-get remove --purge -y powershell || true
|
||||||
|
sudo apt-get remove --purge -y php* || true
|
||||||
|
sudo apt-get remove --purge -y ruby* || true
|
||||||
|
sudo apt-get remove --purge -y mono-* || true
|
||||||
|
sudo apt-get autoremove -y
|
||||||
|
sudo apt-get clean
|
||||||
|
sudo rm -rf /usr/lib/jvm
|
||||||
|
sudo rm -rf /usr/local/.ghcup
|
||||||
|
sudo rm -rf /usr/local/lib/android
|
||||||
|
sudo rm -rf /usr/share/dotnet
|
||||||
|
sudo rm -rf /usr/share/swift
|
||||||
|
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||||
|
|
||||||
|
# BuildJet runners lack /opt/hostedtoolcache, which setup-python and setup-qemu expect
|
||||||
|
- name: Ensure hostedtoolcache exists
|
||||||
|
shell: bash
|
||||||
|
run: sudo mkdir -p /opt/hostedtoolcache && sudo chown $USER:$USER /opt/hostedtoolcache
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
if: inputs.setup-python == 'true'
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ inputs.nodejs-version }}
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: "**/package-lock.json"
|
||||||
|
|
||||||
|
- name: Set up Docker QEMU
|
||||||
|
if: inputs.setup-docker == 'true'
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
if: inputs.setup-docker == 'true'
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Configure sccache
|
||||||
|
if: inputs.setup-sccache == 'true'
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || '');
|
||||||
|
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||||
88
.github/workflows/start-cli.yaml
vendored
Normal file
88
.github/workflows/start-cli.yaml
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
name: start-cli
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
environment:
|
||||||
|
type: choice
|
||||||
|
description: Environment
|
||||||
|
options:
|
||||||
|
- NONE
|
||||||
|
- dev
|
||||||
|
- unstable
|
||||||
|
- dev-unstable
|
||||||
|
runner:
|
||||||
|
type: choice
|
||||||
|
description: Runner
|
||||||
|
options:
|
||||||
|
- standard
|
||||||
|
- fast
|
||||||
|
arch:
|
||||||
|
type: choice
|
||||||
|
description: Architecture
|
||||||
|
options:
|
||||||
|
- ALL
|
||||||
|
- x86_64
|
||||||
|
- x86_64-apple
|
||||||
|
- aarch64
|
||||||
|
- aarch64-apple
|
||||||
|
- riscv64
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- next/*
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- next/*
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODEJS_VERSION: "24.11.0"
|
||||||
|
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
compile:
|
||||||
|
name: Build Debian Package
|
||||||
|
if: github.event.pull_request.draft != true
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
triple: >-
|
||||||
|
${{
|
||||||
|
fromJson('{
|
||||||
|
"x86_64": ["x86_64-unknown-linux-musl"],
|
||||||
|
"x86_64-apple": ["x86_64-apple-darwin"],
|
||||||
|
"aarch64": ["aarch64-unknown-linux-musl"],
|
||||||
|
"x86_64-apple": ["aarch64-apple-darwin"],
|
||||||
|
"riscv64": ["riscv64gc-unknown-linux-musl"],
|
||||||
|
"ALL": ["x86_64-unknown-linux-musl", "x86_64-apple-darwin", "aarch64-unknown-linux-musl", "aarch64-apple-darwin", "riscv64gc-unknown-linux-musl"]
|
||||||
|
}')[github.event.inputs.platform || 'ALL']
|
||||||
|
}}
|
||||||
|
runs-on: ${{ fromJson('["ubuntu-latest", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
|
||||||
|
steps:
|
||||||
|
- name: Mount tmpfs
|
||||||
|
if: ${{ github.event.inputs.runner == 'fast' }}
|
||||||
|
run: sudo mount -t tmpfs tmpfs .
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- uses: ./.github/actions/setup-build
|
||||||
|
with:
|
||||||
|
nodejs-version: ${{ env.NODEJS_VERSION }}
|
||||||
|
|
||||||
|
- name: Make
|
||||||
|
run: TARGET=${{ matrix.triple }} make cli
|
||||||
|
env:
|
||||||
|
PLATFORM: ${{ matrix.arch }}
|
||||||
|
SCCACHE_GHA_ENABLED: on
|
||||||
|
SCCACHE_GHA_VERSION: 0
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: start-cli_${{ matrix.triple }}
|
||||||
|
path: core/target/${{ matrix.triple }}/release/start-cli
|
||||||
173
.github/workflows/start-registry.yaml
vendored
Normal file
173
.github/workflows/start-registry.yaml
vendored
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
name: start-registry
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
environment:
|
||||||
|
type: choice
|
||||||
|
description: Environment
|
||||||
|
options:
|
||||||
|
- NONE
|
||||||
|
- dev
|
||||||
|
- unstable
|
||||||
|
- dev-unstable
|
||||||
|
runner:
|
||||||
|
type: choice
|
||||||
|
description: Runner
|
||||||
|
options:
|
||||||
|
- standard
|
||||||
|
- fast
|
||||||
|
arch:
|
||||||
|
type: choice
|
||||||
|
description: Architecture
|
||||||
|
options:
|
||||||
|
- ALL
|
||||||
|
- x86_64
|
||||||
|
- aarch64
|
||||||
|
- riscv64
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- next/*
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- next/*
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODEJS_VERSION: "24.11.0"
|
||||||
|
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
compile:
|
||||||
|
name: Build Debian Package
|
||||||
|
if: github.event.pull_request.draft != true
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
arch: >-
|
||||||
|
${{
|
||||||
|
fromJson('{
|
||||||
|
"x86_64": ["x86_64"],
|
||||||
|
"aarch64": ["aarch64"],
|
||||||
|
"riscv64": ["riscv64"],
|
||||||
|
"ALL": ["x86_64", "aarch64", "riscv64"]
|
||||||
|
}')[github.event.inputs.platform || 'ALL']
|
||||||
|
}}
|
||||||
|
runs-on: ${{ fromJson('["ubuntu-latest", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
|
||||||
|
steps:
|
||||||
|
- name: Mount tmpfs
|
||||||
|
if: ${{ github.event.inputs.runner == 'fast' }}
|
||||||
|
run: sudo mount -t tmpfs tmpfs .
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- uses: ./.github/actions/setup-build
|
||||||
|
with:
|
||||||
|
nodejs-version: ${{ env.NODEJS_VERSION }}
|
||||||
|
|
||||||
|
- name: Make
|
||||||
|
run: make registry-deb
|
||||||
|
env:
|
||||||
|
PLATFORM: ${{ matrix.arch }}
|
||||||
|
SCCACHE_GHA_ENABLED: on
|
||||||
|
SCCACHE_GHA_VERSION: 0
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: start-registry_${{ matrix.arch }}.deb
|
||||||
|
path: results/start-registry-*_${{ matrix.arch }}.deb
|
||||||
|
|
||||||
|
create-image:
|
||||||
|
name: Create Docker Image
|
||||||
|
needs: [compile]
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
runs-on: ${{ fromJson('["ubuntu-latest", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
|
||||||
|
steps:
|
||||||
|
- name: Cleaning up unnecessary files
|
||||||
|
run: |
|
||||||
|
sudo apt-get remove --purge -y google-chrome-stable firefox mono-devel
|
||||||
|
sudo apt-get autoremove -y
|
||||||
|
sudo apt-get clean
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
sudo mount -t tmpfs tmpfs .
|
||||||
|
if: ${{ github.event.inputs.runner == 'fast' }}
|
||||||
|
|
||||||
|
- name: Set up docker QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: "Login to GitHub Container Registry"
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{github.actor}}
|
||||||
|
password: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ghcr.io/Start9Labs/startos-registry
|
||||||
|
tags: |
|
||||||
|
type=raw,value=${{ github.ref_name }}
|
||||||
|
|
||||||
|
- name: Download debian package
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
pattern: start-registry_*.deb
|
||||||
|
|
||||||
|
- name: Map matrix.arch to docker platform
|
||||||
|
run: |
|
||||||
|
platforms=""
|
||||||
|
for deb in *.deb; do
|
||||||
|
filename=$(basename "$deb" .deb)
|
||||||
|
arch="${filename#*_}"
|
||||||
|
case "$arch" in
|
||||||
|
x86_64)
|
||||||
|
platform="linux/amd64"
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
platform="linux/arm64"
|
||||||
|
;;
|
||||||
|
riscv64)
|
||||||
|
platform="linux/riscv64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown architecture: $arch" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ -z "$platforms" ]; then
|
||||||
|
platforms="$platform"
|
||||||
|
else
|
||||||
|
platforms="$platforms,$platform"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "DOCKER_PLATFORM=$platforms" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
cat | docker buildx build --platform "$DOCKER_PLATFORM" --push -t ${{ steps.meta.outputs.tags }} -f - . << 'EOF'
|
||||||
|
FROM debian:trixie
|
||||||
|
|
||||||
|
ADD *.deb .
|
||||||
|
|
||||||
|
RUN apt-get install -y ./*_$(uname -m).deb && rm *.deb
|
||||||
|
|
||||||
|
VOLUME /var/lib/startos
|
||||||
|
|
||||||
|
ENV RUST_LOG=startos=debug
|
||||||
|
|
||||||
|
ENTRYPOINT ["start-registryd"]
|
||||||
|
|
||||||
|
EOF
|
||||||
84
.github/workflows/start-tunnel.yaml
vendored
Normal file
84
.github/workflows/start-tunnel.yaml
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
name: start-tunnel
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
environment:
|
||||||
|
type: choice
|
||||||
|
description: Environment
|
||||||
|
options:
|
||||||
|
- NONE
|
||||||
|
- dev
|
||||||
|
- unstable
|
||||||
|
- dev-unstable
|
||||||
|
runner:
|
||||||
|
type: choice
|
||||||
|
description: Runner
|
||||||
|
options:
|
||||||
|
- standard
|
||||||
|
- fast
|
||||||
|
arch:
|
||||||
|
type: choice
|
||||||
|
description: Architecture
|
||||||
|
options:
|
||||||
|
- ALL
|
||||||
|
- x86_64
|
||||||
|
- aarch64
|
||||||
|
- riscv64
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- next/*
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- next/*
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODEJS_VERSION: "24.11.0"
|
||||||
|
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
compile:
|
||||||
|
name: Build Debian Package
|
||||||
|
if: github.event.pull_request.draft != true
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
arch: >-
|
||||||
|
${{
|
||||||
|
fromJson('{
|
||||||
|
"x86_64": ["x86_64"],
|
||||||
|
"aarch64": ["aarch64"],
|
||||||
|
"riscv64": ["riscv64"],
|
||||||
|
"ALL": ["x86_64", "aarch64", "riscv64"]
|
||||||
|
}')[github.event.inputs.platform || 'ALL']
|
||||||
|
}}
|
||||||
|
runs-on: ${{ fromJson('["ubuntu-latest", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
|
||||||
|
steps:
|
||||||
|
- name: Mount tmpfs
|
||||||
|
if: ${{ github.event.inputs.runner == 'fast' }}
|
||||||
|
run: sudo mount -t tmpfs tmpfs .
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- uses: ./.github/actions/setup-build
|
||||||
|
with:
|
||||||
|
nodejs-version: ${{ env.NODEJS_VERSION }}
|
||||||
|
|
||||||
|
- name: Make
|
||||||
|
run: make tunnel-deb
|
||||||
|
env:
|
||||||
|
PLATFORM: ${{ matrix.arch }}
|
||||||
|
SCCACHE_GHA_ENABLED: on
|
||||||
|
SCCACHE_GHA_VERSION: 0
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: start-tunnel_${{ matrix.arch }}.deb
|
||||||
|
path: results/start-tunnel-*_${{ matrix.arch }}.deb
|
||||||
169
.github/workflows/startos-iso.yaml
vendored
169
.github/workflows/startos-iso.yaml
vendored
@@ -27,7 +27,7 @@ on:
|
|||||||
- x86_64-nonfree
|
- x86_64-nonfree
|
||||||
- aarch64
|
- aarch64
|
||||||
- aarch64-nonfree
|
- aarch64-nonfree
|
||||||
- raspberrypi
|
# - raspberrypi
|
||||||
- riscv64
|
- riscv64
|
||||||
deploy:
|
deploy:
|
||||||
type: choice
|
type: choice
|
||||||
@@ -45,6 +45,10 @@ on:
|
|||||||
- master
|
- master
|
||||||
- next/*
|
- next/*
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODEJS_VERSION: "24.11.0"
|
NODEJS_VERSION: "24.11.0"
|
||||||
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}'
|
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}'
|
||||||
@@ -52,6 +56,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
compile:
|
compile:
|
||||||
name: Compile Base Binaries
|
name: Compile Base Binaries
|
||||||
|
if: github.event.pull_request.draft != true
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
@@ -64,49 +69,38 @@ jobs:
|
|||||||
"aarch64-nonfree": ["aarch64"],
|
"aarch64-nonfree": ["aarch64"],
|
||||||
"raspberrypi": ["aarch64"],
|
"raspberrypi": ["aarch64"],
|
||||||
"riscv64": ["riscv64"],
|
"riscv64": ["riscv64"],
|
||||||
"ALL": ["x86_64", "aarch64"]
|
"ALL": ["x86_64", "aarch64", "riscv64"]
|
||||||
}')[github.event.inputs.platform || 'ALL']
|
}')[github.event.inputs.platform || 'ALL']
|
||||||
}}
|
}}
|
||||||
runs-on: ${{ fromJson('["ubuntu-22.04", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
|
runs-on: >-
|
||||||
|
${{
|
||||||
|
fromJson(
|
||||||
|
format(
|
||||||
|
'["{0}", "{1}"]',
|
||||||
|
fromJson('{
|
||||||
|
"x86_64": "ubuntu-latest",
|
||||||
|
"aarch64": "ubuntu-24.04-arm",
|
||||||
|
"riscv64": "ubuntu-latest"
|
||||||
|
}')[matrix.arch],
|
||||||
|
fromJson('{
|
||||||
|
"x86_64": "buildjet-32vcpu-ubuntu-2204",
|
||||||
|
"aarch64": "buildjet-32vcpu-ubuntu-2204-arm",
|
||||||
|
"riscv64": "buildjet-32vcpu-ubuntu-2204"
|
||||||
|
}')[matrix.arch]
|
||||||
|
)
|
||||||
|
)[github.event.inputs.runner == 'fast']
|
||||||
|
}}
|
||||||
steps:
|
steps:
|
||||||
- run: |
|
- name: Mount tmpfs
|
||||||
sudo mount -t tmpfs tmpfs .
|
|
||||||
if: ${{ github.event.inputs.runner == 'fast' }}
|
if: ${{ github.event.inputs.runner == 'fast' }}
|
||||||
|
run: sudo mount -t tmpfs tmpfs .
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
- uses: ./.github/actions/setup-build
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
nodejs-version: ${{ env.NODEJS_VERSION }}
|
||||||
|
setup-python: "true"
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: ${{ env.NODEJS_VERSION }}
|
|
||||||
|
|
||||||
- name: Set up docker QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Set up system dependencies
|
|
||||||
run: sudo apt-get update && sudo apt-get install -y qemu-user-static systemd-container squashfuse
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Configure sccache
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || '');
|
|
||||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
|
||||||
|
|
||||||
- name: Use Beta Toolchain
|
|
||||||
run: rustup default beta
|
|
||||||
|
|
||||||
- name: Setup Cross
|
|
||||||
run: cargo install cross --git https://github.com/cross-rs/cross
|
|
||||||
|
|
||||||
- name: Make
|
- name: Make
|
||||||
run: make ARCH=${{ matrix.arch }} compiled-${{ matrix.arch }}.tar
|
run: make ARCH=${{ matrix.arch }} compiled-${{ matrix.arch }}.tar
|
||||||
@@ -124,13 +118,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", "aarch64", "aarch64-nonfree", "raspberrypi"]
|
["x86_64", "x86_64-nonfree", "aarch64", "aarch64-nonfree", "riscv64"]
|
||||||
]',
|
]',
|
||||||
github.event.inputs.platform || 'ALL'
|
github.event.inputs.platform || 'ALL'
|
||||||
)
|
)
|
||||||
@@ -140,7 +135,15 @@ jobs:
|
|||||||
${{
|
${{
|
||||||
fromJson(
|
fromJson(
|
||||||
format(
|
format(
|
||||||
'["ubuntu-22.04", "{0}"]',
|
'["{0}", "{1}"]',
|
||||||
|
fromJson('{
|
||||||
|
"x86_64": "ubuntu-latest",
|
||||||
|
"x86_64-nonfree": "ubuntu-latest",
|
||||||
|
"aarch64": "ubuntu-24.04-arm",
|
||||||
|
"aarch64-nonfree": "ubuntu-24.04-arm",
|
||||||
|
"raspberrypi": "ubuntu-24.04-arm",
|
||||||
|
"riscv64": "ubuntu-24.04-arm",
|
||||||
|
}')[matrix.platform],
|
||||||
fromJson('{
|
fromJson('{
|
||||||
"x86_64": "buildjet-8vcpu-ubuntu-2204",
|
"x86_64": "buildjet-8vcpu-ubuntu-2204",
|
||||||
"x86_64-nonfree": "buildjet-8vcpu-ubuntu-2204",
|
"x86_64-nonfree": "buildjet-8vcpu-ubuntu-2204",
|
||||||
@@ -166,35 +169,37 @@ jobs:
|
|||||||
}}
|
}}
|
||||||
steps:
|
steps:
|
||||||
- name: Free space
|
- name: Free space
|
||||||
run: rm -rf /opt/hostedtoolcache*
|
run: |
|
||||||
|
sudo apt-get remove --purge -y azure-cli || true
|
||||||
|
sudo apt-get remove --purge -y firefox || true
|
||||||
|
sudo apt-get remove --purge -y ghc-* || true
|
||||||
|
sudo apt-get remove --purge -y google-cloud-sdk || true
|
||||||
|
sudo apt-get remove --purge -y google-chrome-stable || true
|
||||||
|
sudo apt-get remove --purge -y powershell || true
|
||||||
|
sudo apt-get remove --purge -y php* || true
|
||||||
|
sudo apt-get remove --purge -y ruby* || true
|
||||||
|
sudo apt-get remove --purge -y mono-* || true
|
||||||
|
sudo apt-get autoremove -y
|
||||||
|
sudo apt-get clean
|
||||||
|
sudo rm -rf /usr/lib/jvm # All JDKs
|
||||||
|
sudo rm -rf /usr/local/.ghcup # Haskell toolchain
|
||||||
|
sudo rm -rf /usr/local/lib/android # Android SDK/NDK, emulator
|
||||||
|
sudo rm -rf /usr/share/dotnet # .NET SDKs
|
||||||
|
sudo rm -rf /usr/share/swift # Swift toolchain (if present)
|
||||||
|
sudo rm -rf "$AGENT_TOOLSDIRECTORY" # Pre-cached tool cache (Go, Node, etc.)
|
||||||
if: ${{ github.event.inputs.runner != 'fast' }}
|
if: ${{ github.event.inputs.runner != 'fast' }}
|
||||||
|
|
||||||
|
# BuildJet runners lack /opt/hostedtoolcache, which setup-qemu expects
|
||||||
|
- name: Ensure hostedtoolcache exists
|
||||||
|
run: sudo mkdir -p /opt/hostedtoolcache && sudo chown $USER:$USER /opt/hostedtoolcache
|
||||||
|
|
||||||
|
- name: Set up docker QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.x"
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y qemu-user-static
|
|
||||||
wget https://deb.debian.org/debian/pool/main/d/debspawn/debspawn_0.6.2-1_all.deb
|
|
||||||
sha256sum ./debspawn_0.6.2-1_all.deb | grep 37ef27458cb1e35e8bce4d4f639b06b4b3866fc0b9191ec6b9bd157afd06a817
|
|
||||||
sudo apt-get install -y ./debspawn_0.6.2-1_all.deb
|
|
||||||
|
|
||||||
- name: Configure debspawn
|
|
||||||
run: |
|
|
||||||
sudo mkdir -p /etc/debspawn/
|
|
||||||
echo "AllowUnsafePermissions=true" | sudo tee /etc/debspawn/global.toml
|
|
||||||
sudo mkdir -p /var/tmp/debspawn
|
|
||||||
|
|
||||||
- run: sudo mount -t tmpfs tmpfs /var/tmp/debspawn
|
|
||||||
if: ${{ github.event.inputs.runner == 'fast' && (matrix.platform == 'x86_64' || matrix.platform == 'x86_64-nonfree') }}
|
|
||||||
|
|
||||||
- name: Download compiled artifacts
|
- name: Download compiled artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -207,22 +212,19 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p web/node_modules
|
mkdir -p web/node_modules
|
||||||
mkdir -p web/dist/raw
|
mkdir -p web/dist/raw
|
||||||
mkdir -p core/startos/bindings
|
mkdir -p core/bindings
|
||||||
mkdir -p sdk/base/lib/osBindings
|
mkdir -p sdk/base/lib/osBindings
|
||||||
mkdir -p container-runtime/node_modules
|
mkdir -p container-runtime/node_modules
|
||||||
mkdir -p container-runtime/dist
|
mkdir -p container-runtime/dist
|
||||||
mkdir -p container-runtime/dist/node_modules
|
mkdir -p container-runtime/dist/node_modules
|
||||||
mkdir -p core/startos/bindings
|
|
||||||
mkdir -p sdk/dist
|
mkdir -p sdk/dist
|
||||||
mkdir -p sdk/baseDist
|
mkdir -p sdk/baseDist
|
||||||
mkdir -p patch-db/client/node_modules
|
mkdir -p patch-db/client/node_modules
|
||||||
mkdir -p patch-db/client/dist
|
mkdir -p patch-db/client/dist
|
||||||
mkdir -p web/.angular
|
mkdir -p web/.angular
|
||||||
mkdir -p web/dist/raw/ui
|
mkdir -p web/dist/raw/ui
|
||||||
mkdir -p web/dist/raw/install-wizard
|
|
||||||
mkdir -p web/dist/raw/setup-wizard
|
mkdir -p web/dist/raw/setup-wizard
|
||||||
mkdir -p web/dist/static/ui
|
mkdir -p web/dist/static/ui
|
||||||
mkdir -p web/dist/static/install-wizard
|
|
||||||
mkdir -p web/dist/static/setup-wizard
|
mkdir -p web/dist/static/setup-wizard
|
||||||
PLATFORM=${{ matrix.platform }} make -t compiled-${{ env.ARCH }}.tar
|
PLATFORM=${{ matrix.platform }} make -t compiled-${{ env.ARCH }}.tar
|
||||||
|
|
||||||
@@ -252,40 +254,3 @@ jobs:
|
|||||||
name: ${{ matrix.platform }}.img
|
name: ${{ matrix.platform }}.img
|
||||||
path: results/*.img
|
path: results/*.img
|
||||||
if: ${{ matrix.platform == 'raspberrypi' }}
|
if: ${{ matrix.platform == 'raspberrypi' }}
|
||||||
|
|
||||||
- name: Upload OTA to registry
|
|
||||||
run: >-
|
|
||||||
PLATFORM=${{ matrix.platform }} make upload-ota TARGET="${{
|
|
||||||
fromJson('{
|
|
||||||
"alpha": "alpha-registry-x.start9.com",
|
|
||||||
"beta": "beta-registry.start9.com",
|
|
||||||
}')[github.event.inputs.deploy]
|
|
||||||
}}" KEY="${{
|
|
||||||
fromJson(
|
|
||||||
format('{{
|
|
||||||
"alpha": "{0}",
|
|
||||||
"beta": "{1}",
|
|
||||||
}}', secrets.ALPHA_INDEX_KEY, secrets.BETA_INDEX_KEY)
|
|
||||||
)[github.event.inputs.deploy]
|
|
||||||
}}"
|
|
||||||
if: ${{ github.event.inputs.deploy != '' && github.event.inputs.deploy != 'NONE' }}
|
|
||||||
|
|
||||||
index:
|
|
||||||
if: ${{ github.event.inputs.deploy != '' && github.event.inputs.deploy != 'NONE' }}
|
|
||||||
needs: [image]
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- run: >-
|
|
||||||
curl "https://${{
|
|
||||||
fromJson('{
|
|
||||||
"alpha": "alpha-registry-x.start9.com",
|
|
||||||
"beta": "beta-registry.start9.com",
|
|
||||||
}')[github.event.inputs.deploy]
|
|
||||||
}}:8443/resync.cgi?key=${{
|
|
||||||
fromJson(
|
|
||||||
format('{{
|
|
||||||
"alpha": "{0}",
|
|
||||||
"beta": "{1}",
|
|
||||||
}}', secrets.ALPHA_INDEX_KEY, secrets.BETA_INDEX_KEY)
|
|
||||||
)[github.event.inputs.deploy]
|
|
||||||
}}"
|
|
||||||
|
|||||||
21
.github/workflows/test.yaml
vendored
21
.github/workflows/test.yaml
vendored
@@ -10,6 +10,10 @@ on:
|
|||||||
- master
|
- master
|
||||||
- next/*
|
- next/*
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODEJS_VERSION: "24.11.0"
|
NODEJS_VERSION: "24.11.0"
|
||||||
ENVIRONMENT: dev-unstable
|
ENVIRONMENT: dev-unstable
|
||||||
@@ -17,21 +21,18 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Run Automated Tests
|
name: Run Automated Tests
|
||||||
runs-on: ubuntu-22.04
|
if: github.event.pull_request.draft != true
|
||||||
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
- uses: ./.github/actions/setup-build
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODEJS_VERSION }}
|
nodejs-version: ${{ env.NODEJS_VERSION }}
|
||||||
|
free-space: "false"
|
||||||
- name: Use Beta Toolchain
|
setup-docker: "false"
|
||||||
run: rustup default beta
|
setup-sccache: "false"
|
||||||
|
|
||||||
- name: Setup Cross
|
|
||||||
run: cargo install cross --git https://github.com/cross-rs/cross
|
|
||||||
|
|
||||||
- name: Build And Run Tests
|
- name: Build And Run Tests
|
||||||
run: make test
|
run: make test
|
||||||
|
|||||||
24
.gitignore
vendored
24
.gitignore
vendored
@@ -1,28 +1,22 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
/*.img
|
*.img
|
||||||
/*.img.gz
|
*.img.gz
|
||||||
/*.img.xz
|
*.img.xz
|
||||||
/*-raspios-bullseye-arm64-lite.img
|
*.zip
|
||||||
/*-raspios-bullseye-arm64-lite.zip
|
|
||||||
/product_key.txt
|
/product_key.txt
|
||||||
/*_product_key.txt
|
/*_product_key.txt
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
deploy_web.sh
|
deploy_web.sh
|
||||||
deploy_web.sh
|
|
||||||
secrets.db
|
secrets.db
|
||||||
.vscode/
|
.vscode/
|
||||||
/cargo-deps/**/*
|
/build/env/*.txt
|
||||||
/PLATFORM.txt
|
*.deb
|
||||||
/ENVIRONMENT.txt
|
|
||||||
/GIT_HASH.txt
|
|
||||||
/VERSION.txt
|
|
||||||
/*.deb
|
|
||||||
/target
|
/target
|
||||||
/*.squashfs
|
*.squashfs
|
||||||
/results
|
/results
|
||||||
/dpkg-workdir
|
/dpkg-workdir
|
||||||
/compiled.tar
|
/compiled.tar
|
||||||
/compiled-*.tar
|
/compiled-*.tar
|
||||||
/firmware
|
/build/lib/firmware
|
||||||
/tmp
|
tmp
|
||||||
186
Makefile
186
Makefile
@@ -1,46 +1,44 @@
|
|||||||
ls-files = $(shell git ls-files --cached --others --exclude-standard $1)
|
ls-files = $(shell git ls-files --cached --others --exclude-standard $1)
|
||||||
PROFILE = release
|
PROFILE = release
|
||||||
|
|
||||||
PLATFORM_FILE := $(shell ./check-platform.sh)
|
PLATFORM_FILE := $(shell ./build/env/check-platform.sh)
|
||||||
ENVIRONMENT_FILE := $(shell ./check-environment.sh)
|
ENVIRONMENT_FILE := $(shell ./build/env/check-environment.sh)
|
||||||
GIT_HASH_FILE := $(shell ./check-git-hash.sh)
|
GIT_HASH_FILE := $(shell ./build/env/check-git-hash.sh)
|
||||||
VERSION_FILE := $(shell ./check-version.sh)
|
VERSION_FILE := $(shell ./build/env/check-version.sh)
|
||||||
BASENAME := $(shell PROJECT=startos ./basename.sh)
|
BASENAME := $(shell PROJECT=startos ./build/env/basename.sh)
|
||||||
PLATFORM := $(shell if [ -f ./PLATFORM.txt ]; then cat ./PLATFORM.txt; else echo unknown; fi)
|
PLATFORM := $(shell if [ -f $(PLATFORM_FILE) ]; then cat $(PLATFORM_FILE); else echo unknown; fi)
|
||||||
ARCH := $(shell if [ "$(PLATFORM)" = "raspberrypi" ]; then echo aarch64; else echo $(PLATFORM) | sed 's/-nonfree$$//g'; fi)
|
ARCH := $(shell if [ "$(PLATFORM)" = "raspberrypi" ]; then echo aarch64; else echo $(PLATFORM) | sed 's/-nonfree$$//g'; fi)
|
||||||
RUST_ARCH := $(shell if [ "$(ARCH)" = "riscv64" ]; then echo riscv64gc; else echo $(ARCH); fi)
|
RUST_ARCH := $(shell if [ "$(ARCH)" = "riscv64" ]; then echo riscv64gc; else echo $(ARCH); fi)
|
||||||
REGISTRY_BASENAME := $(shell PROJECT=start-registry PLATFORM=$(ARCH) ./basename.sh)
|
REGISTRY_BASENAME := $(shell PROJECT=start-registry PLATFORM=$(ARCH) ./build/env/basename.sh)
|
||||||
TUNNEL_BASENAME := $(shell PROJECT=start-tunnel PLATFORM=$(ARCH) ./basename.sh)
|
TUNNEL_BASENAME := $(shell PROJECT=start-tunnel PLATFORM=$(ARCH) ./build/env/basename.sh)
|
||||||
IMAGE_TYPE=$(shell if [ "$(PLATFORM)" = raspberrypi ]; then echo img; else echo iso; fi)
|
IMAGE_TYPE=$(shell if [ "$(PLATFORM)" = raspberrypi ]; then echo img; else echo iso; fi)
|
||||||
WEB_UIS := web/dist/raw/ui/index.html web/dist/raw/setup-wizard/index.html web/dist/raw/install-wizard/index.html
|
WEB_UIS := web/dist/raw/ui/index.html web/dist/raw/setup-wizard/index.html
|
||||||
COMPRESSED_WEB_UIS := web/dist/static/ui/index.html web/dist/static/setup-wizard/index.html web/dist/static/install-wizard/index.html
|
COMPRESSED_WEB_UIS := web/dist/static/ui/index.html web/dist/static/setup-wizard/index.html
|
||||||
FIRMWARE_ROMS := ./firmware/$(PLATFORM) $(shell jq --raw-output '.[] | select(.platform[] | contains("$(PLATFORM)")) | "./firmware/$(PLATFORM)/" + .id + ".rom.gz"' build/lib/firmware.json)
|
FIRMWARE_ROMS := build/lib/firmware/$(PLATFORM) $(shell jq --raw-output '.[] | select(.platform[] | contains("$(PLATFORM)")) | "./build/lib/firmware/$(PLATFORM)/" + .id + ".rom.gz"' build/lib/firmware.json)
|
||||||
BUILD_SRC := $(call ls-files, build) build/lib/depends build/lib/conflicts $(FIRMWARE_ROMS)
|
BUILD_SRC := $(call ls-files, build/lib) build/lib/depends build/lib/conflicts $(FIRMWARE_ROMS)
|
||||||
IMAGE_RECIPE_SRC := $(call ls-files, image-recipe/)
|
IMAGE_RECIPE_SRC := $(call ls-files, build/image-recipe/)
|
||||||
STARTD_SRC := core/startos/startd.service $(BUILD_SRC)
|
STARTD_SRC := core/startd.service $(BUILD_SRC)
|
||||||
CORE_SRC := $(call ls-files, core) $(shell git ls-files --recurse-submodules patch-db) $(GIT_HASH_FILE)
|
CORE_SRC := $(call ls-files, core) $(shell git ls-files --recurse-submodules patch-db) $(GIT_HASH_FILE)
|
||||||
WEB_SHARED_SRC := $(call ls-files, web/projects/shared) $(call ls-files, web/projects/marketplace) $(shell ls -p web/ | grep -v / | sed 's/^/web\//g') web/node_modules/.package-lock.json web/config.json patch-db/client/dist/index.js sdk/baseDist/package.json web/patchdb-ui-seed.json sdk/dist/package.json
|
WEB_SHARED_SRC := $(call ls-files, web/projects/shared) $(call ls-files, web/projects/marketplace) $(shell ls -p web/ | grep -v / | sed 's/^/web\//g') web/node_modules/.package-lock.json web/config.json patch-db/client/dist/index.js sdk/baseDist/package.json web/patchdb-ui-seed.json sdk/dist/package.json
|
||||||
WEB_UI_SRC := $(call ls-files, web/projects/ui)
|
WEB_UI_SRC := $(call ls-files, web/projects/ui)
|
||||||
WEB_SETUP_WIZARD_SRC := $(call ls-files, web/projects/setup-wizard)
|
WEB_SETUP_WIZARD_SRC := $(call ls-files, web/projects/setup-wizard)
|
||||||
WEB_INSTALL_WIZARD_SRC := $(call ls-files, web/projects/install-wizard)
|
|
||||||
WEB_START_TUNNEL_SRC := $(call ls-files, web/projects/start-tunnel)
|
WEB_START_TUNNEL_SRC := $(call ls-files, web/projects/start-tunnel)
|
||||||
PATCH_DB_CLIENT_SRC := $(shell git ls-files --recurse-submodules patch-db/client)
|
PATCH_DB_CLIENT_SRC := $(shell git ls-files --recurse-submodules patch-db/client)
|
||||||
GZIP_BIN := $(shell which pigz || which gzip)
|
GZIP_BIN := $(shell which pigz || which gzip)
|
||||||
TAR_BIN := $(shell which gtar || which tar)
|
TAR_BIN := $(shell which gtar || which tar)
|
||||||
COMPILED_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox core/target/$(RUST_ARCH)-unknown-linux-musl/release/containerbox container-runtime/rootfs.$(ARCH).squashfs
|
COMPILED_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox core/target/$(RUST_ARCH)-unknown-linux-musl/release/start-container container-runtime/rootfs.$(ARCH).squashfs
|
||||||
STARTOS_TARGETS := $(STARTD_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_FILE) $(COMPILED_TARGETS) cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/startos-backup-fs $(PLATFORM_FILE) \
|
STARTOS_TARGETS := $(STARTD_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_FILE) $(COMPILED_TARGETS) target/$(RUST_ARCH)-unknown-linux-musl/release/startos-backup-fs $(PLATFORM_FILE) \
|
||||||
$(shell if [ "$(PLATFORM)" = "raspberrypi" ]; then \
|
$(shell if [ "$(PLATFORM)" = "raspberrypi" ]; then \
|
||||||
echo cargo-deps/aarch64-unknown-linux-musl/release/pi-beep; \
|
echo target/aarch64-unknown-linux-musl/release/pi-beep; \
|
||||||
fi) \
|
fi) \
|
||||||
$(shell /bin/bash -c 'if [[ "${ENVIRONMENT}" =~ (^|-)unstable($$|-) ]]; then \
|
$(shell /bin/bash -c 'if [[ "${ENVIRONMENT}" =~ (^|-)unstable($$|-) ]]; then \
|
||||||
echo cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/flamegraph; \
|
echo target/$(RUST_ARCH)-unknown-linux-musl/release/flamegraph; \
|
||||||
fi') \
|
fi') \
|
||||||
$(shell /bin/bash -c 'if [[ "${ENVIRONMENT}" =~ (^|-)console($$|-) ]]; then \
|
$(shell /bin/bash -c 'if [[ "${ENVIRONMENT}" =~ (^|-)console($$|-) ]]; then \
|
||||||
echo cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/tokio-console; \
|
echo target/$(RUST_ARCH)-unknown-linux-musl/release/tokio-console; \
|
||||||
fi')
|
fi')
|
||||||
REGISTRY_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/registrybox core/startos/start-registryd.service
|
REGISTRY_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/registrybox core/start-registryd.service
|
||||||
TUNNEL_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox core/startos/start-tunneld.service
|
TUNNEL_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox core/start-tunneld.service
|
||||||
REBUILD_TYPES = 1
|
|
||||||
|
|
||||||
ifeq ($(REMOTE),)
|
ifeq ($(REMOTE),)
|
||||||
mkdir = mkdir -p $1
|
mkdir = mkdir -p $1
|
||||||
@@ -63,7 +61,7 @@ endif
|
|||||||
|
|
||||||
.DELETE_ON_ERROR:
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
.PHONY: all metadata install clean format cli uis ui reflash deb $(IMAGE_TYPE) squashfs wormhole wormhole-deb test test-core test-sdk test-container-runtime registry install-registry tunnel install-tunnel
|
.PHONY: all metadata install clean format install-cli cli uis ui reflash deb $(IMAGE_TYPE) squashfs wormhole wormhole-deb test test-core test-sdk test-container-runtime registry install-registry tunnel install-tunnel ts-bindings
|
||||||
|
|
||||||
all: $(STARTOS_TARGETS)
|
all: $(STARTOS_TARGETS)
|
||||||
|
|
||||||
@@ -74,7 +72,7 @@ metadata: $(VERSION_FILE) $(PLATFORM_FILE) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE)
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf core/target
|
rm -rf core/target
|
||||||
rm -rf core/startos/bindings
|
rm -rf core/bindings
|
||||||
rm -rf web/.angular
|
rm -rf web/.angular
|
||||||
rm -f web/config.json
|
rm -f web/config.json
|
||||||
rm -rf web/node_modules
|
rm -rf web/node_modules
|
||||||
@@ -82,7 +80,7 @@ clean:
|
|||||||
rm -rf patch-db/client/node_modules
|
rm -rf patch-db/client/node_modules
|
||||||
rm -rf patch-db/client/dist
|
rm -rf patch-db/client/dist
|
||||||
rm -rf patch-db/target
|
rm -rf patch-db/target
|
||||||
rm -rf cargo-deps
|
rm -rf target
|
||||||
rm -rf dpkg-workdir
|
rm -rf dpkg-workdir
|
||||||
rm -rf image-recipe/deb
|
rm -rf image-recipe/deb
|
||||||
rm -rf results
|
rm -rf results
|
||||||
@@ -90,14 +88,8 @@ clean:
|
|||||||
rm -rf container-runtime/dist
|
rm -rf container-runtime/dist
|
||||||
rm -rf container-runtime/node_modules
|
rm -rf container-runtime/node_modules
|
||||||
rm -f container-runtime/*.squashfs
|
rm -f container-runtime/*.squashfs
|
||||||
if [ -d container-runtime/tmp/combined ] && mountpoint container-runtime/tmp/combined; then sudo umount container-runtime/tmp/combined; fi
|
|
||||||
if [ -d container-runtime/tmp/lower ] && mountpoint container-runtime/tmp/lower; then sudo umount container-runtime/tmp/lower; fi
|
|
||||||
rm -rf container-runtime/tmp
|
|
||||||
(cd sdk && make clean)
|
(cd sdk && make clean)
|
||||||
rm -f ENVIRONMENT.txt
|
rm -f env/*.txt
|
||||||
rm -f PLATFORM.txt
|
|
||||||
rm -f GIT_HASH.txt
|
|
||||||
rm -f VERSION.txt
|
|
||||||
|
|
||||||
format:
|
format:
|
||||||
cd core && cargo +nightly fmt
|
cd core && cargo +nightly fmt
|
||||||
@@ -113,8 +105,11 @@ test-sdk: $(call ls-files, sdk) sdk/base/lib/osBindings/index.ts
|
|||||||
test-container-runtime: container-runtime/node_modules/.package-lock.json $(call ls-files, container-runtime/src) container-runtime/package.json container-runtime/tsconfig.json
|
test-container-runtime: container-runtime/node_modules/.package-lock.json $(call ls-files, container-runtime/src) container-runtime/package.json container-runtime/tsconfig.json
|
||||||
cd container-runtime && npm test
|
cd container-runtime && npm test
|
||||||
|
|
||||||
cli:
|
install-cli: $(GIT_HASH_FILE)
|
||||||
./core/install-cli.sh
|
./core/build/build-cli.sh --install
|
||||||
|
|
||||||
|
cli: $(GIT_HASH_FILE)
|
||||||
|
./core/build/build-cli.sh
|
||||||
|
|
||||||
registry: core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/registrybox
|
registry: core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/registrybox
|
||||||
|
|
||||||
@@ -125,49 +120,49 @@ install-registry: $(REGISTRY_TARGETS)
|
|||||||
$(call ln,/usr/bin/start-registrybox,$(DESTDIR)/usr/bin/start-registry)
|
$(call ln,/usr/bin/start-registrybox,$(DESTDIR)/usr/bin/start-registry)
|
||||||
|
|
||||||
$(call mkdir,$(DESTDIR)/lib/systemd/system)
|
$(call mkdir,$(DESTDIR)/lib/systemd/system)
|
||||||
$(call cp,core/startos/start-registryd.service,$(DESTDIR)/lib/systemd/system/start-registryd.service)
|
$(call cp,core/start-registryd.service,$(DESTDIR)/lib/systemd/system/start-registryd.service)
|
||||||
|
|
||||||
core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/registrybox: $(CORE_SRC) $(ENVIRONMENT_FILE)
|
core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/registrybox: $(CORE_SRC) $(ENVIRONMENT_FILE)
|
||||||
ARCH=$(ARCH) PROFILE=$(PROFILE) ./core/build-registrybox.sh
|
ARCH=$(ARCH) PROFILE=$(PROFILE) ./core/build/build-registrybox.sh
|
||||||
|
|
||||||
tunnel: core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox
|
tunnel: core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox
|
||||||
|
|
||||||
install-tunnel: core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox core/startos/start-tunneld.service
|
install-tunnel: core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox core/start-tunneld.service
|
||||||
$(call mkdir,$(DESTDIR)/usr/bin)
|
$(call mkdir,$(DESTDIR)/usr/bin)
|
||||||
$(call cp,core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox,$(DESTDIR)/usr/bin/start-tunnelbox)
|
$(call cp,core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox,$(DESTDIR)/usr/bin/start-tunnelbox)
|
||||||
$(call ln,/usr/bin/start-tunnelbox,$(DESTDIR)/usr/bin/start-tunneld)
|
$(call ln,/usr/bin/start-tunnelbox,$(DESTDIR)/usr/bin/start-tunneld)
|
||||||
$(call ln,/usr/bin/start-tunnelbox,$(DESTDIR)/usr/bin/start-tunnel)
|
$(call ln,/usr/bin/start-tunnelbox,$(DESTDIR)/usr/bin/start-tunnel)
|
||||||
|
|
||||||
$(call mkdir,$(DESTDIR)/lib/systemd/system)
|
$(call mkdir,$(DESTDIR)/lib/systemd/system)
|
||||||
$(call cp,core/startos/start-tunneld.service,$(DESTDIR)/lib/systemd/system/start-tunneld.service)
|
$(call cp,core/start-tunneld.service,$(DESTDIR)/lib/systemd/system/start-tunneld.service)
|
||||||
|
|
||||||
$(call mkdir,$(DESTDIR)/usr/lib/startos/scripts)
|
$(call mkdir,$(DESTDIR)/usr/lib/startos/scripts)
|
||||||
$(call cp,build/lib/scripts/forward-port,$(DESTDIR)/usr/lib/startos/scripts/forward-port)
|
$(call cp,build/lib/scripts/forward-port,$(DESTDIR)/usr/lib/startos/scripts/forward-port)
|
||||||
|
|
||||||
core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox: $(CORE_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) web/dist/static/start-tunnel/index.html
|
core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox: $(CORE_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) web/dist/static/start-tunnel/index.html
|
||||||
ARCH=$(ARCH) PROFILE=$(PROFILE) ./core/build-tunnelbox.sh
|
ARCH=$(ARCH) PROFILE=$(PROFILE) ./core/build/build-tunnelbox.sh
|
||||||
|
|
||||||
deb: results/$(BASENAME).deb
|
deb: results/$(BASENAME).deb
|
||||||
|
|
||||||
results/$(BASENAME).deb: dpkg-build.sh $(call ls-files,debian/startos) $(STARTOS_TARGETS)
|
results/$(BASENAME).deb: debian/dpkg-build.sh $(call ls-files,debian/startos) $(STARTOS_TARGETS)
|
||||||
PLATFORM=$(PLATFORM) REQUIRES=debian ./build/os-compat/run-compat.sh ./dpkg-build.sh
|
PLATFORM=$(PLATFORM) REQUIRES=debian ./build/os-compat/run-compat.sh ./debian/dpkg-build.sh
|
||||||
|
|
||||||
registry-deb: results/$(REGISTRY_BASENAME).deb
|
registry-deb: results/$(REGISTRY_BASENAME).deb
|
||||||
|
|
||||||
results/$(REGISTRY_BASENAME).deb: 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 ./build/os-compat/run-compat.sh ./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
|
||||||
|
|
||||||
results/$(TUNNEL_BASENAME).deb: dpkg-build.sh $(call ls-files,debian/start-tunnel) $(TUNNEL_TARGETS)
|
results/$(TUNNEL_BASENAME).deb: debian/dpkg-build.sh $(call ls-files,debian/start-tunnel) $(TUNNEL_TARGETS) build/lib/scripts/forward-port
|
||||||
PROJECT=start-tunnel PLATFORM=$(ARCH) REQUIRES=debian DEPENDS=wireguard-tools,iptables ./build/os-compat/run-compat.sh ./dpkg-build.sh
|
PROJECT=start-tunnel PLATFORM=$(ARCH) REQUIRES=debian DEPENDS=wireguard-tools,iptables,conntrack ./build/os-compat/run-compat.sh ./debian/dpkg-build.sh
|
||||||
|
|
||||||
$(IMAGE_TYPE): results/$(BASENAME).$(IMAGE_TYPE)
|
$(IMAGE_TYPE): results/$(BASENAME).$(IMAGE_TYPE)
|
||||||
|
|
||||||
squashfs: results/$(BASENAME).squashfs
|
squashfs: results/$(BASENAME).squashfs
|
||||||
|
|
||||||
results/$(BASENAME).$(IMAGE_TYPE) results/$(BASENAME).squashfs: $(IMAGE_RECIPE_SRC) results/$(BASENAME).deb
|
results/$(BASENAME).$(IMAGE_TYPE) results/$(BASENAME).squashfs: $(IMAGE_RECIPE_SRC) results/$(BASENAME).deb
|
||||||
./image-recipe/run-local-build.sh "results/$(BASENAME).deb"
|
ARCH=$(ARCH) ./build/image-recipe/run-local-build.sh "results/$(BASENAME).deb"
|
||||||
|
|
||||||
# For creating os images. DO NOT USE
|
# For creating os images. DO NOT USE
|
||||||
install: $(STARTOS_TARGETS)
|
install: $(STARTOS_TARGETS)
|
||||||
@@ -176,18 +171,18 @@ install: $(STARTOS_TARGETS)
|
|||||||
$(call cp,core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox,$(DESTDIR)/usr/bin/startbox)
|
$(call cp,core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox,$(DESTDIR)/usr/bin/startbox)
|
||||||
$(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/startd)
|
$(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/startd)
|
||||||
$(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/start-cli)
|
$(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/start-cli)
|
||||||
if [ "$(PLATFORM)" = "raspberrypi" ]; then $(call cp,cargo-deps/aarch64-unknown-linux-musl/release/pi-beep,$(DESTDIR)/usr/bin/pi-beep); fi
|
if [ "$(PLATFORM)" = "raspberrypi" ]; then $(call cp,target/aarch64-unknown-linux-musl/release/pi-beep,$(DESTDIR)/usr/bin/pi-beep); fi
|
||||||
if /bin/bash -c '[[ "${ENVIRONMENT}" =~ (^|-)unstable($$|-) ]]'; then \
|
if /bin/bash -c '[[ "${ENVIRONMENT}" =~ (^|-)unstable($$|-) ]]'; then \
|
||||||
$(call cp,cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/flamegraph,$(DESTDIR)/usr/bin/flamegraph); \
|
$(call cp,target/$(RUST_ARCH)-unknown-linux-musl/release/flamegraph,$(DESTDIR)/usr/bin/flamegraph); \
|
||||||
fi
|
fi
|
||||||
if /bin/bash -c '[[ "${ENVIRONMENT}" =~ (^|-)console($$|-) ]]'; then \
|
if /bin/bash -c '[[ "${ENVIRONMENT}" =~ (^|-)console($$|-) ]]'; then \
|
||||||
$(call cp,cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/tokio-console,$(DESTDIR)/usr/bin/tokio-console); \
|
$(call cp,target/$(RUST_ARCH)-unknown-linux-musl/release/tokio-console,$(DESTDIR)/usr/bin/tokio-console); \
|
||||||
fi
|
fi
|
||||||
$(call cp,cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/startos-backup-fs,$(DESTDIR)/usr/bin/startos-backup-fs)
|
$(call cp,target/$(RUST_ARCH)-unknown-linux-musl/release/startos-backup-fs,$(DESTDIR)/usr/bin/startos-backup-fs)
|
||||||
$(call ln,/usr/bin/startos-backup-fs,$(DESTDIR)/usr/sbin/mount.backup-fs)
|
$(call ln,/usr/bin/startos-backup-fs,$(DESTDIR)/usr/sbin/mount.backup-fs)
|
||||||
|
|
||||||
$(call mkdir,$(DESTDIR)/lib/systemd/system)
|
$(call mkdir,$(DESTDIR)/lib/systemd/system)
|
||||||
$(call cp,core/startos/startd.service,$(DESTDIR)/lib/systemd/system/startd.service)
|
$(call cp,core/startd.service,$(DESTDIR)/lib/systemd/system/startd.service)
|
||||||
|
|
||||||
$(call mkdir,$(DESTDIR)/usr/lib)
|
$(call mkdir,$(DESTDIR)/usr/lib)
|
||||||
$(call rm,$(DESTDIR)/usr/lib/startos)
|
$(call rm,$(DESTDIR)/usr/lib/startos)
|
||||||
@@ -195,18 +190,16 @@ install: $(STARTOS_TARGETS)
|
|||||||
$(call mkdir,$(DESTDIR)/usr/lib/startos/container-runtime)
|
$(call mkdir,$(DESTDIR)/usr/lib/startos/container-runtime)
|
||||||
$(call cp,container-runtime/rootfs.$(ARCH).squashfs,$(DESTDIR)/usr/lib/startos/container-runtime/rootfs.squashfs)
|
$(call cp,container-runtime/rootfs.$(ARCH).squashfs,$(DESTDIR)/usr/lib/startos/container-runtime/rootfs.squashfs)
|
||||||
|
|
||||||
$(call cp,PLATFORM.txt,$(DESTDIR)/usr/lib/startos/PLATFORM.txt)
|
$(call cp,build/env/PLATFORM.txt,$(DESTDIR)/usr/lib/startos/PLATFORM.txt)
|
||||||
$(call cp,ENVIRONMENT.txt,$(DESTDIR)/usr/lib/startos/ENVIRONMENT.txt)
|
$(call cp,build/env/ENVIRONMENT.txt,$(DESTDIR)/usr/lib/startos/ENVIRONMENT.txt)
|
||||||
$(call cp,GIT_HASH.txt,$(DESTDIR)/usr/lib/startos/GIT_HASH.txt)
|
$(call cp,build/env/GIT_HASH.txt,$(DESTDIR)/usr/lib/startos/GIT_HASH.txt)
|
||||||
$(call cp,VERSION.txt,$(DESTDIR)/usr/lib/startos/VERSION.txt)
|
$(call cp,build/env/VERSION.txt,$(DESTDIR)/usr/lib/startos/VERSION.txt)
|
||||||
|
|
||||||
$(call cp,firmware/$(PLATFORM),$(DESTDIR)/usr/lib/startos/firmware)
|
|
||||||
|
|
||||||
update-overlay: $(STARTOS_TARGETS)
|
update-overlay: $(STARTOS_TARGETS)
|
||||||
@echo "\033[33m!!! THIS WILL ONLY REFLASH YOUR DEVICE IN MEMORY !!!\033[0m"
|
@echo "\033[33m!!! THIS WILL ONLY REFLASH YOUR DEVICE IN MEMORY !!!\033[0m"
|
||||||
@echo "\033[33mALL CHANGES WILL BE REVERTED IF YOU RESTART THE DEVICE\033[0m"
|
@echo "\033[33mALL CHANGES WILL BE REVERTED IF YOU RESTART THE DEVICE\033[0m"
|
||||||
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
||||||
@if [ "`ssh $(REMOTE) 'cat /usr/lib/startos/VERSION.txt'`" != "`cat ./VERSION.txt`" ]; then >&2 echo "StartOS requires migrations: update-overlay is unavailable." && false; fi
|
@if [ "`ssh $(REMOTE) 'cat /usr/lib/startos/VERSION.txt'`" != "`cat $(VERSION_FILE)`" ]; then >&2 echo "StartOS requires migrations: update-overlay is unavailable." && false; fi
|
||||||
$(call ssh,"sudo systemctl stop startd")
|
$(call ssh,"sudo systemctl stop startd")
|
||||||
$(MAKE) install REMOTE=$(REMOTE) SSHPASS=$(SSHPASS) PLATFORM=$(PLATFORM)
|
$(MAKE) install REMOTE=$(REMOTE) SSHPASS=$(SSHPASS) PLATFORM=$(PLATFORM)
|
||||||
$(call ssh,"sudo systemctl start startd")
|
$(call ssh,"sudo systemctl start startd")
|
||||||
@@ -226,7 +219,7 @@ wormhole-squashfs: 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}'))
|
||||||
@echo "Paste the following command into the shell of your StartOS server:"
|
@echo "Paste the following command into the shell of your StartOS server:"
|
||||||
@echo
|
@echo
|
||||||
@wormhole send results/$(BASENAME).squashfs 2>&1 | awk -Winteractive '/wormhole receive/ { printf "sudo sh -c '"'"'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE) && /usr/lib/startos/scripts/prune-boot && cd /media/startos/images && wormhole receive --accept-file %s && CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/use-img ./$(BASENAME).squashfs'"'"'\n", $$3 }'
|
@wormhole send results/$(BASENAME).squashfs 2>&1 | awk -Winteractive '/wormhole receive/ { printf "sudo sh -c '"'"'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE) && /usr/lib/startos/scripts/prune-boot && cd /media/startos/images && wormhole receive --accept-file %s && CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/upgrade ./$(BASENAME).squashfs'"'"'\n", $$3 }'
|
||||||
|
|
||||||
update: $(STARTOS_TARGETS)
|
update: $(STARTOS_TARGETS)
|
||||||
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
||||||
@@ -254,7 +247,7 @@ update-squashfs: results/$(BASENAME).squashfs
|
|||||||
$(call ssh,'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE)')
|
$(call ssh,'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE)')
|
||||||
$(call ssh,'/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/use-img /media/startos/images/next.rootfs')
|
$(call ssh,'sudo CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/upgrade /media/startos/images/next.rootfs')
|
||||||
|
|
||||||
emulate-reflash: $(STARTOS_TARGETS)
|
emulate-reflash: $(STARTOS_TARGETS)
|
||||||
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
||||||
@@ -264,7 +257,7 @@ emulate-reflash: $(STARTOS_TARGETS)
|
|||||||
$(call ssh,'sudo /media/startos/next/usr/lib/startos/scripts/chroot-and-upgrade --no-sync "apt-get install -y $(shell cat ./build/lib/depends)"')
|
$(call ssh,'sudo /media/startos/next/usr/lib/startos/scripts/chroot-and-upgrade --no-sync "apt-get install -y $(shell cat ./build/lib/depends)"')
|
||||||
|
|
||||||
upload-ota: results/$(BASENAME).squashfs
|
upload-ota: results/$(BASENAME).squashfs
|
||||||
TARGET=$(TARGET) KEY=$(KEY) ./upload-ota.sh
|
TARGET=$(TARGET) KEY=$(KEY) ./build/upload-ota.sh
|
||||||
|
|
||||||
container-runtime/debian.$(ARCH).squashfs: ./container-runtime/download-base-image.sh
|
container-runtime/debian.$(ARCH).squashfs: ./container-runtime/download-base-image.sh
|
||||||
ARCH=$(ARCH) ./container-runtime/download-base-image.sh
|
ARCH=$(ARCH) ./container-runtime/download-base-image.sh
|
||||||
@@ -277,14 +270,16 @@ container-runtime/node_modules/.package-lock.json: container-runtime/package-loc
|
|||||||
npm --prefix container-runtime ci
|
npm --prefix container-runtime ci
|
||||||
touch container-runtime/node_modules/.package-lock.json
|
touch container-runtime/node_modules/.package-lock.json
|
||||||
|
|
||||||
sdk/base/lib/osBindings/index.ts: $(shell if [ "$(REBUILD_TYPES)" -ne 0 ]; then echo core/startos/bindings/index.ts; fi)
|
ts-bindings: core/bindings/index.ts
|
||||||
mkdir -p sdk/base/lib/osBindings
|
mkdir -p sdk/base/lib/osBindings
|
||||||
rsync -ac --delete core/startos/bindings/ sdk/base/lib/osBindings/
|
rsync -ac --delete core/bindings/ sdk/base/lib/osBindings/
|
||||||
touch sdk/base/lib/osBindings/index.ts
|
|
||||||
|
|
||||||
core/startos/bindings/index.ts: $(call ls-files, core) $(ENVIRONMENT_FILE)
|
core/bindings/index.ts: $(call ls-files, core) $(ENVIRONMENT_FILE)
|
||||||
./core/build-ts.sh
|
rm -rf core/bindings
|
||||||
touch core/startos/bindings/index.ts
|
./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
|
||||||
|
npm --prefix sdk exec -- prettier --config ./sdk/base/package.json -w ./core/bindings/*.ts
|
||||||
|
touch core/bindings/index.ts
|
||||||
|
|
||||||
sdk/dist/package.json sdk/baseDist/package.json: $(call ls-files, sdk) sdk/base/lib/osBindings/index.ts
|
sdk/dist/package.json sdk/baseDist/package.json: $(call ls-files, sdk) sdk/base/lib/osBindings/index.ts
|
||||||
(cd sdk && make bundle)
|
(cd sdk && make bundle)
|
||||||
@@ -299,22 +294,22 @@ container-runtime/dist/node_modules/.package-lock.json container-runtime/dist/pa
|
|||||||
./container-runtime/install-dist-deps.sh
|
./container-runtime/install-dist-deps.sh
|
||||||
touch container-runtime/dist/node_modules/.package-lock.json
|
touch container-runtime/dist/node_modules/.package-lock.json
|
||||||
|
|
||||||
container-runtime/rootfs.$(ARCH).squashfs: container-runtime/debian.$(ARCH).squashfs container-runtime/container-runtime.service container-runtime/update-image.sh container-runtime/deb-install.sh container-runtime/dist/index.js container-runtime/dist/node_modules/.package-lock.json core/target/$(RUST_ARCH)-unknown-linux-musl/release/containerbox
|
container-runtime/rootfs.$(ARCH).squashfs: container-runtime/debian.$(ARCH).squashfs container-runtime/container-runtime.service container-runtime/update-image.sh container-runtime/update-image-local.sh container-runtime/deb-install.sh container-runtime/dist/index.js container-runtime/dist/node_modules/.package-lock.json core/target/$(RUST_ARCH)-unknown-linux-musl/release/start-container
|
||||||
ARCH=$(ARCH) REQUIRES=linux ./build/os-compat/run-compat.sh ./container-runtime/update-image.sh
|
ARCH=$(ARCH) ./container-runtime/update-image-local.sh
|
||||||
|
|
||||||
build/lib/depends build/lib/conflicts: $(ENVIRONMENT_FILE) $(PLATFORM_FILE) $(shell ls build/dpkg-deps/*)
|
build/lib/depends build/lib/conflicts: $(ENVIRONMENT_FILE) $(PLATFORM_FILE) $(shell ls build/dpkg-deps/*)
|
||||||
PLATFORM=$(PLATFORM) ARCH=$(ARCH) build/dpkg-deps/generate.sh
|
PLATFORM=$(PLATFORM) ARCH=$(ARCH) build/dpkg-deps/generate.sh
|
||||||
|
|
||||||
$(FIRMWARE_ROMS): build/lib/firmware.json download-firmware.sh $(PLATFORM_FILE)
|
$(FIRMWARE_ROMS): build/lib/firmware.json ./build/download-firmware.sh $(PLATFORM_FILE)
|
||||||
./download-firmware.sh $(PLATFORM)
|
./build/download-firmware.sh $(PLATFORM)
|
||||||
|
|
||||||
core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox: $(CORE_SRC) $(COMPRESSED_WEB_UIS) web/patchdb-ui-seed.json $(ENVIRONMENT_FILE)
|
core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox: $(CORE_SRC) $(COMPRESSED_WEB_UIS) web/patchdb-ui-seed.json $(ENVIRONMENT_FILE)
|
||||||
ARCH=$(ARCH) PROFILE=$(PROFILE) ./core/build-startbox.sh
|
ARCH=$(ARCH) PROFILE=$(PROFILE) ./core/build/build-startbox.sh
|
||||||
touch core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox
|
touch core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox
|
||||||
|
|
||||||
core/target/$(RUST_ARCH)-unknown-linux-musl/release/containerbox: $(CORE_SRC) $(ENVIRONMENT_FILE)
|
core/target/$(RUST_ARCH)-unknown-linux-musl/release/start-container: $(CORE_SRC) $(ENVIRONMENT_FILE)
|
||||||
ARCH=$(ARCH) ./core/build-containerbox.sh
|
ARCH=$(ARCH) ./core/build/build-start-container.sh
|
||||||
touch core/target/$(RUST_ARCH)-unknown-linux-musl/release/containerbox
|
touch core/target/$(RUST_ARCH)-unknown-linux-musl/release/start-container
|
||||||
|
|
||||||
web/package-lock.json: web/package.json sdk/baseDist/package.json
|
web/package-lock.json: web/package.json sdk/baseDist/package.json
|
||||||
npm --prefix web i
|
npm --prefix web i
|
||||||
@@ -329,27 +324,27 @@ web/.angular/.updated: patch-db/client/dist/index.js sdk/baseDist/package.json w
|
|||||||
mkdir -p web/.angular
|
mkdir -p web/.angular
|
||||||
touch web/.angular/.updated
|
touch web/.angular/.updated
|
||||||
|
|
||||||
web/dist/raw/ui/index.html: $(WEB_UI_SRC) $(WEB_SHARED_SRC) web/.angular/.updated
|
web/.i18n-checked: $(WEB_SHARED_SRC) $(WEB_UI_SRC) $(WEB_SETUP_WIZARD_SRC) $(WEB_START_TUNNEL_SRC)
|
||||||
|
npm --prefix web run check:i18n
|
||||||
|
touch web/.i18n-checked
|
||||||
|
|
||||||
|
web/dist/raw/ui/index.html: $(WEB_UI_SRC) $(WEB_SHARED_SRC) web/.angular/.updated web/.i18n-checked
|
||||||
npm --prefix web run build:ui
|
npm --prefix web run build:ui
|
||||||
touch web/dist/raw/ui/index.html
|
touch web/dist/raw/ui/index.html
|
||||||
|
|
||||||
web/dist/raw/setup-wizard/index.html: $(WEB_SETUP_WIZARD_SRC) $(WEB_SHARED_SRC) web/.angular/.updated
|
web/dist/raw/setup-wizard/index.html: $(WEB_SETUP_WIZARD_SRC) $(WEB_SHARED_SRC) web/.angular/.updated web/.i18n-checked
|
||||||
npm --prefix web run build:setup
|
npm --prefix web run build:setup
|
||||||
touch web/dist/raw/setup-wizard/index.html
|
touch web/dist/raw/setup-wizard/index.html
|
||||||
|
|
||||||
web/dist/raw/install-wizard/index.html: $(WEB_INSTALL_WIZARD_SRC) $(WEB_SHARED_SRC) web/.angular/.updated
|
web/dist/raw/start-tunnel/index.html: $(WEB_START_TUNNEL_SRC) $(WEB_SHARED_SRC) web/.angular/.updated web/.i18n-checked
|
||||||
npm --prefix web run build:install
|
|
||||||
touch web/dist/raw/install-wizard/index.html
|
|
||||||
|
|
||||||
web/dist/raw/start-tunnel/index.html: $(WEB_START_TUNNEL_SRC) $(WEB_SHARED_SRC) web/.angular/.updated
|
|
||||||
npm --prefix web run build:tunnel
|
npm --prefix web run build:tunnel
|
||||||
touch web/dist/raw/start-tunnel/index.html
|
touch web/dist/raw/start-tunnel/index.html
|
||||||
|
|
||||||
web/dist/static/%/index.html: web/dist/raw/%/index.html
|
web/dist/static/%/index.html: web/dist/raw/%/index.html
|
||||||
./compress-uis.sh $*
|
./web/compress-uis.sh $*
|
||||||
|
|
||||||
web/config.json: $(GIT_HASH_FILE) web/config-sample.json
|
web/config.json: $(GIT_HASH_FILE) $(ENVIRONMENT_FILE) web/config-sample.json web/update-config.sh
|
||||||
jq '.useMocks = false' web/config-sample.json | jq '.gitHash = "$(shell cat GIT_HASH.txt)"' > web/config.json
|
./web/update-config.sh
|
||||||
|
|
||||||
patch-db/client/node_modules/.package-lock.json: patch-db/client/package.json
|
patch-db/client/node_modules/.package-lock.json: patch-db/client/package.json
|
||||||
npm --prefix patch-db/client ci
|
npm --prefix patch-db/client ci
|
||||||
@@ -370,14 +365,17 @@ uis: $(WEB_UIS)
|
|||||||
# this is a convenience step to build the UI
|
# this is a convenience step to build the UI
|
||||||
ui: web/dist/raw/ui
|
ui: web/dist/raw/ui
|
||||||
|
|
||||||
cargo-deps/aarch64-unknown-linux-musl/release/pi-beep:
|
target/aarch64-unknown-linux-musl/release/pi-beep: ./build/build-cargo-dep.sh
|
||||||
ARCH=aarch64 ./build-cargo-dep.sh pi-beep
|
ARCH=aarch64 ./build/build-cargo-dep.sh pi-beep
|
||||||
|
|
||||||
cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/tokio-console:
|
target/$(RUST_ARCH)-unknown-linux-musl/release/tokio-console: ./build/build-cargo-dep.sh
|
||||||
ARCH=$(ARCH) PREINSTALL="apk add musl-dev pkgconfig" ./build-cargo-dep.sh tokio-console
|
ARCH=$(ARCH) ./build/build-cargo-dep.sh tokio-console
|
||||||
|
touch $@
|
||||||
|
|
||||||
cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/startos-backup-fs:
|
target/$(RUST_ARCH)-unknown-linux-musl/release/startos-backup-fs: ./build/build-cargo-dep.sh
|
||||||
ARCH=$(ARCH) PREINSTALL="apk add fuse3 fuse3-dev fuse3-static musl-dev pkgconfig" ./build-cargo-dep.sh --git https://github.com/Start9Labs/start-fs.git startos-backup-fs
|
ARCH=$(ARCH) ./build/build-cargo-dep.sh --git https://github.com/Start9Labs/start-fs.git startos-backup-fs
|
||||||
|
touch $@
|
||||||
|
|
||||||
cargo-deps/$(RUST_ARCH)-unknown-linux-musl/release/flamegraph:
|
target/$(RUST_ARCH)-unknown-linux-musl/release/flamegraph: ./build/build-cargo-dep.sh
|
||||||
ARCH=$(ARCH) PREINSTALL="apk add musl-dev pkgconfig" ./build-cargo-dep.sh flamegraph
|
ARCH=$(ARCH) ./build/build-cargo-dep.sh flamegraph
|
||||||
|
touch $@
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
# StartTunnel
|
|
||||||
|
|
||||||
A self-hosted Wiregaurd VPN optimized for creating VLANs and reverse tunneling to personal servers.
|
|
||||||
|
|
||||||
You can think of StartTunnel as "virtual router in the cloud"
|
|
||||||
|
|
||||||
Use it for private, remote access, to self-hosted services running on a personal server, or to expose self-hosted services to the public Internet without revealing the host server's IP address.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Create Subnets**: Each subnet creates a private, virtual local area network (VLAN), similar to the LAN created by a home router.
|
|
||||||
|
|
||||||
- **Add Devices**: When you add a device (server, phone, laptop) to a subnet, it receives a LAN IP address on that subnet as well as a unique Wireguard config that must be copied, downloaded, or scanned into the device.
|
|
||||||
|
|
||||||
- **Forward Ports**: Forwarding a port creates a "reverse tunnel", exposing a specific port on a specific device to the public Internet.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
1. Rent a low cost VPS. For most use cases, the cheapest option should be enough.
|
|
||||||
|
|
||||||
- It must have a dedicated public IP address.
|
|
||||||
- For (CPU), memory (RAM), and storage (disk), choose the minimum spec.
|
|
||||||
- For transfer (bandwidth), it depends on (1) your use case and (2) your home Internet's _upload_ speed. Even if you intend to serve large files or stream content from your server, there is no reason to pay for speeds that exceed your home Internet's upload speed.
|
|
||||||
|
|
||||||
1. Provision the VPS with the latest version of Debian.
|
|
||||||
|
|
||||||
1. Access the VPS via SSH.
|
|
||||||
|
|
||||||
1. Install StartTunnel:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
TMP_DIR=$(mktemp -d) && (cd $TMP_DIR && wget https://github.com/Start9Labs/start-os/releases/download/v0.4.0-alpha.12/start-tunnel-0.4.0-alpha.12-68f401b_$(uname -m).deb && apt-get install -y ./start-tunnel-0.4.0-alpha.12-68f401b_$(uname -m).deb) && rm -rf $TMP_DIR && systemctl start start-tunneld && echo "Installation Succeeded"
|
|
||||||
```
|
|
||||||
|
|
||||||
5. [Initialize the web interface](#web-interface) (recommended)
|
|
||||||
|
|
||||||
## CLI
|
|
||||||
|
|
||||||
By default, StartTunnel is managed via the `start-tunnel` command line interface, which is self-documented.
|
|
||||||
|
|
||||||
```
|
|
||||||
start-tunnel --help
|
|
||||||
```
|
|
||||||
|
|
||||||
## Web Interface
|
|
||||||
|
|
||||||
If you choose to enable the web interface (recommended in most cases), StartTunnel can be accessed as a website from the browser, or programmatically via API.
|
|
||||||
|
|
||||||
1. Initialize the web interface.
|
|
||||||
|
|
||||||
start-tunnel web init
|
|
||||||
|
|
||||||
1. When prompted, select the IP address at which to host the web interface. In many cases, there will be only one IP address.
|
|
||||||
|
|
||||||
1. When prompted, enter the port at which to host the web interface. The default is 8443, and we recommend using it. If you change the default, choose an uncommon port to avoid conflicts.
|
|
||||||
|
|
||||||
1. Select whether to autogenerate a self-signed certificate or provide your own certificate and key. If you choose to autogenerate, you will be asked to list all IP addresses and domains for which to sign the certificate. For example, if you intend to access your StartTunnel web UI at a domain, include the domain in the list.
|
|
||||||
|
|
||||||
1. You will receive a success message with 3 pieces of information:
|
|
||||||
|
|
||||||
- <https://IP:port>: the URL where you can reach your personal web interface.
|
|
||||||
- Password: an autogenerated password for your interface. If you lose/forget it, you can reset using the CLI.
|
|
||||||
- Root Certificate Authority: the Root CA of your StartTunnel instance. If not already, trust it in your browser or system keychain.
|
|
||||||
201
agents/VERSION_BUMP.md
Normal file
201
agents/VERSION_BUMP.md
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
# StartOS Version Bump Guide
|
||||||
|
|
||||||
|
This document explains how to bump the StartOS version across the entire codebase.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
When bumping from version `X.Y.Z-alpha.N` to `X.Y.Z-alpha.N+1`, you need to update files in multiple locations across the repository. The `// VERSION_BUMP` comment markers indicate where changes are needed.
|
||||||
|
|
||||||
|
## Files to Update
|
||||||
|
|
||||||
|
### 1. Core Rust Crate Version
|
||||||
|
|
||||||
|
**File: `core/Cargo.toml`**
|
||||||
|
|
||||||
|
Update the version string (line ~18):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
version = "0.4.0-alpha.15" # VERSION_BUMP
|
||||||
|
```
|
||||||
|
|
||||||
|
**File: `core/Cargo.lock`**
|
||||||
|
|
||||||
|
This file is auto-generated. After updating `Cargo.toml`, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd core
|
||||||
|
cargo check
|
||||||
|
```
|
||||||
|
|
||||||
|
This will update the version in `Cargo.lock` automatically.
|
||||||
|
|
||||||
|
### 2. Create New Version Migration Module
|
||||||
|
|
||||||
|
**File: `core/src/version/vX_Y_Z_alpha_N+1.rs`**
|
||||||
|
|
||||||
|
Create a new version file by copying the previous version and updating:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use exver::{PreReleaseSegment, VersionRange};
|
||||||
|
|
||||||
|
use super::v0_3_5::V0_3_0_COMPAT;
|
||||||
|
use super::{VersionT, v0_4_0_alpha_14}; // Update to previous version
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref V0_4_0_alpha_15: exver::Version = exver::Version::new(
|
||||||
|
[0, 4, 0],
|
||||||
|
[PreReleaseSegment::String("alpha".into()), 15.into()] // Update number
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
pub struct Version;
|
||||||
|
|
||||||
|
impl VersionT for Version {
|
||||||
|
type Previous = v0_4_0_alpha_14::Version; // Update to previous version
|
||||||
|
type PreUpRes = ();
|
||||||
|
|
||||||
|
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn semver(self) -> exver::Version {
|
||||||
|
V0_4_0_alpha_15.clone() // Update version name
|
||||||
|
}
|
||||||
|
fn compat(self) -> &'static VersionRange {
|
||||||
|
&V0_3_0_COMPAT
|
||||||
|
}
|
||||||
|
#[instrument(skip_all)]
|
||||||
|
fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<Value, Error> {
|
||||||
|
// Add migration logic here if needed
|
||||||
|
Ok(Value::Null)
|
||||||
|
}
|
||||||
|
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||||
|
// Add rollback logic here if needed
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Update Version Module Registry
|
||||||
|
|
||||||
|
**File: `core/src/version/mod.rs`**
|
||||||
|
|
||||||
|
Make changes in **5 locations**:
|
||||||
|
|
||||||
|
#### Location 1: Module Declaration (~line 57)
|
||||||
|
|
||||||
|
Add the new module after the previous version:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
mod v0_4_0_alpha_14;
|
||||||
|
mod v0_4_0_alpha_15; // Add this
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Location 2: Current Type Alias (~line 59)
|
||||||
|
|
||||||
|
Update the `Current` type and move the `// VERSION_BUMP` comment:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub type Current = v0_4_0_alpha_15::Version; // VERSION_BUMP
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Location 3: Version Enum (~line 175)
|
||||||
|
|
||||||
|
Remove `// VERSION_BUMP` from the previous version, add new variant, add comment:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
V0_4_0_alpha_14(Wrapper<v0_4_0_alpha_14::Version>),
|
||||||
|
V0_4_0_alpha_15(Wrapper<v0_4_0_alpha_15::Version>), // VERSION_BUMP
|
||||||
|
Other(exver::Version),
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Location 4: as_version_t() Match (~line 233)
|
||||||
|
|
||||||
|
Remove `// VERSION_BUMP`, add new match arm, add comment:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
Self::V0_4_0_alpha_14(v) => DynVersion(Box::new(v.0)),
|
||||||
|
Self::V0_4_0_alpha_15(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
|
||||||
|
Self::Other(v) => {
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Location 5: as_exver() Match (~line 284, inside #[cfg(test)])
|
||||||
|
|
||||||
|
Remove `// VERSION_BUMP`, add new match arm, add comment:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
Version::V0_4_0_alpha_14(Wrapper(x)) => x.semver(),
|
||||||
|
Version::V0_4_0_alpha_15(Wrapper(x)) => x.semver(), // VERSION_BUMP
|
||||||
|
Version::Other(x) => x.clone(),
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. SDK TypeScript Version
|
||||||
|
|
||||||
|
**File: `sdk/package/lib/StartSdk.ts`**
|
||||||
|
|
||||||
|
Update the OSVersion constant (~line 64):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export const OSVersion = testTypeVersion("0.4.0-alpha.15");
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Web UI Package Version
|
||||||
|
|
||||||
|
**File: `web/package.json`**
|
||||||
|
|
||||||
|
Update the version field:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "startos-ui",
|
||||||
|
"version": "0.4.0-alpha.15",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**File: `web/package-lock.json`**
|
||||||
|
|
||||||
|
This file is auto-generated, but it's faster to update manually. Find all instances of "startos-ui" and update the version field.
|
||||||
|
|
||||||
|
## Verification Step
|
||||||
|
|
||||||
|
```
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## VERSION_BUMP Comment Pattern
|
||||||
|
|
||||||
|
The `// VERSION_BUMP` comment serves as a marker for where to make changes next time:
|
||||||
|
|
||||||
|
- Always **remove** it from the old location
|
||||||
|
- **Add** the new version entry
|
||||||
|
- **Move** the comment to mark the new location
|
||||||
|
|
||||||
|
This pattern helps you quickly find all the places that need updating in the next version bump.
|
||||||
|
|
||||||
|
## Summary Checklist
|
||||||
|
|
||||||
|
- [ ] Update `core/Cargo.toml` version
|
||||||
|
- [ ] Create new `core/src/version/vX_Y_Z_alpha_N+1.rs` file
|
||||||
|
- [ ] Update `core/src/version/mod.rs` in 5 locations
|
||||||
|
- [ ] Run `cargo check` to update `core/Cargo.lock`
|
||||||
|
- [ ] Update `sdk/package/lib/StartSdk.ts` OSVersion
|
||||||
|
- [ ] Update `web/package.json` and `web/package-lock.json` version
|
||||||
|
- [ ] Verify all changes compile/build successfully
|
||||||
|
|
||||||
|
## Migration Logic
|
||||||
|
|
||||||
|
The `up()` and `down()` methods in the version file handle database migrations:
|
||||||
|
|
||||||
|
- **up()**: Migrates the database from the previous version to this version
|
||||||
|
- **down()**: Rolls back from this version to the previous version
|
||||||
|
- **pre_up()**: Runs before migration, useful for pre-migration checks or data gathering
|
||||||
|
|
||||||
|
If no migration is needed, return `Ok(Value::Null)` for `up()` and `Ok(())` for `down()`.
|
||||||
|
|
||||||
|
For complex migrations, you may need to:
|
||||||
|
|
||||||
|
1. Update `type PreUpRes` to pass data between `pre_up()` and `up()`
|
||||||
|
2. Implement database transformations in the `up()` method
|
||||||
|
3. Implement reverse transformations in `down()` for rollback support
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
shopt -s expand_aliases
|
|
||||||
|
|
||||||
if [ "$0" != "./build-cargo-dep.sh" ]; then
|
|
||||||
>&2 echo "Must be run from start-os directory"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
USE_TTY=
|
|
||||||
if tty -s; then
|
|
||||||
USE_TTY="-it"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
fi
|
|
||||||
|
|
||||||
DOCKER_PLATFORM="linux/${ARCH}"
|
|
||||||
if [ "$ARCH" = aarch64 ] || [ "$ARCH" = arm64 ]; then
|
|
||||||
DOCKER_PLATFORM="linux/arm64"
|
|
||||||
elif [ "$ARCH" = x86_64 ]; then
|
|
||||||
DOCKER_PLATFORM="linux/amd64"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p cargo-deps
|
|
||||||
alias 'rust-musl-builder'='docker run $USE_TTY --platform=${DOCKER_PLATFORM} --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)"/cargo-deps:/home/rust/src -w /home/rust/src -P rust:alpine'
|
|
||||||
|
|
||||||
PREINSTALL=${PREINSTALL:-true}
|
|
||||||
|
|
||||||
rust-musl-builder sh -c "$PREINSTALL && cargo install $* --target-dir /home/rust/src --target=$ARCH-unknown-linux-musl"
|
|
||||||
sudo chown -R $USER cargo-deps
|
|
||||||
sudo chown -R $USER ~/.cargo
|
|
||||||
0
build/README.md
Normal file
0
build/README.md
Normal file
26
build/build-cargo-dep.sh
Executable file
26
build/build-cargo-dep.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
||||||
|
|
||||||
|
set -e
|
||||||
|
shopt -s expand_aliases
|
||||||
|
|
||||||
|
if [ -z "$ARCH" ]; then
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
fi
|
||||||
|
|
||||||
|
RUST_ARCH="$ARCH"
|
||||||
|
if [ "$ARCH" = "riscv64" ]; then
|
||||||
|
RUST_ARCH="riscv64gc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p target
|
||||||
|
|
||||||
|
source core/build/builder-alias.sh
|
||||||
|
|
||||||
|
RUSTFLAGS="-C target-feature=+crt-static"
|
||||||
|
|
||||||
|
rust-zig-builder cargo-zigbuild install $* --target-dir /workdir/target/ --target=$RUST_ARCH-unknown-linux-musl
|
||||||
|
if [ "$(ls -nd "target/$RUST_ARCH-unknown-linux-musl/release/${!#}" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
rust-zig-builder sh -c "chown -R $UID:$UID target && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
fi
|
||||||
@@ -11,13 +11,13 @@ if [ -z "$PLATFORM" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf ./firmware/$PLATFORM
|
rm -rf ./lib/firmware/$PLATFORM
|
||||||
mkdir -p ./firmware/$PLATFORM
|
mkdir -p ./lib/firmware/$PLATFORM
|
||||||
|
|
||||||
cd ./firmware/$PLATFORM
|
cd ./lib/firmware/$PLATFORM
|
||||||
|
|
||||||
firmwares=()
|
firmwares=()
|
||||||
while IFS= read -r line; do firmwares+=("$line"); done < <(jq -c ".[] | select(.platform[] | contains(\"$PLATFORM\"))" ../../build/lib/firmware.json)
|
while IFS= read -r line; do firmwares+=("$line"); done < <(jq -c ".[] | select(.platform[] | contains(\"$PLATFORM\"))" ../../firmware.json)
|
||||||
for firmware in "${firmwares[@]}"; do
|
for firmware in "${firmwares[@]}"; do
|
||||||
if [ -n "$firmware" ]; then
|
if [ -n "$firmware" ]; then
|
||||||
id=$(echo "$firmware" | jq --raw-output '.id')
|
id=$(echo "$firmware" | jq --raw-output '.id')
|
||||||
@@ -3,10 +3,12 @@ avahi-utils
|
|||||||
b3sum
|
b3sum
|
||||||
bash-completion
|
bash-completion
|
||||||
beep
|
beep
|
||||||
|
binfmt-support
|
||||||
bmon
|
bmon
|
||||||
btrfs-progs
|
btrfs-progs
|
||||||
ca-certificates
|
ca-certificates
|
||||||
cifs-utils
|
cifs-utils
|
||||||
|
conntrack
|
||||||
cryptsetup
|
cryptsetup
|
||||||
curl
|
curl
|
||||||
dmidecode
|
dmidecode
|
||||||
@@ -14,12 +16,12 @@ dnsutils
|
|||||||
dosfstools
|
dosfstools
|
||||||
e2fsprogs
|
e2fsprogs
|
||||||
ecryptfs-utils
|
ecryptfs-utils
|
||||||
|
equivs
|
||||||
exfatprogs
|
exfatprogs
|
||||||
flashrom
|
flashrom
|
||||||
fuse3
|
fuse3
|
||||||
grub-common
|
grub-common
|
||||||
grub-efi
|
grub-efi
|
||||||
grub2-common
|
|
||||||
htop
|
htop
|
||||||
httpdirfs
|
httpdirfs
|
||||||
iotop
|
iotop
|
||||||
@@ -44,6 +46,7 @@ openssh-server
|
|||||||
podman
|
podman
|
||||||
psmisc
|
psmisc
|
||||||
qemu-guest-agent
|
qemu-guest-agent
|
||||||
|
qemu-user-static
|
||||||
rfkill
|
rfkill
|
||||||
rsync
|
rsync
|
||||||
samba-common-bin
|
samba-common-bin
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ FEATURES+=("${ARCH}")
|
|||||||
if [ "$ARCH" != "$PLATFORM" ]; then
|
if [ "$ARCH" != "$PLATFORM" ]; then
|
||||||
FEATURES+=("${PLATFORM}")
|
FEATURES+=("${PLATFORM}")
|
||||||
fi
|
fi
|
||||||
|
if [[ "$PLATFORM" =~ -nonfree$ ]]; then
|
||||||
|
FEATURES+=("nonfree")
|
||||||
|
fi
|
||||||
|
|
||||||
feature_file_checker='
|
feature_file_checker='
|
||||||
/^#/ { next }
|
/^#/ { next }
|
||||||
|
|||||||
10
build/dpkg-deps/nonfree.depends
Normal file
10
build/dpkg-deps/nonfree.depends
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
+ firmware-amd-graphics
|
||||||
|
+ firmware-atheros
|
||||||
|
+ firmware-brcm80211
|
||||||
|
+ firmware-iwlwifi
|
||||||
|
+ firmware-libertas
|
||||||
|
+ firmware-misc-nonfree
|
||||||
|
+ firmware-realtek
|
||||||
|
+ nvidia-container-toolkit
|
||||||
|
# + nvidia-driver
|
||||||
|
# + nvidia-kernel-dkms
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
- grub-common
|
|
||||||
- grub-efi
|
- grub-efi
|
||||||
- grub2-common
|
|
||||||
+ parted
|
+ parted
|
||||||
+ raspberrypi-net-mods
|
+ raspberrypi-net-mods
|
||||||
+ raspberrypi-sys-mods
|
+ raspberrypi-sys-mods
|
||||||
|
|||||||
0
basename.sh → build/env/basename.sh
vendored
0
basename.sh → build/env/basename.sh
vendored
@@ -1,8 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
if ! [ -f ./ENVIRONMENT.txt ] || [ "$(cat ./ENVIRONMENT.txt)" != "$ENVIRONMENT" ]; then
|
if ! [ -f ./ENVIRONMENT.txt ] || [ "$(cat ./ENVIRONMENT.txt)" != "$ENVIRONMENT" ]; then
|
||||||
>&2 echo "Updating ENVIRONMENT.txt to \"$ENVIRONMENT\""
|
>&2 echo "Updating ENVIRONMENT.txt to \"$ENVIRONMENT\""
|
||||||
echo -n "$ENVIRONMENT" > ./ENVIRONMENT.txt
|
echo -n "$ENVIRONMENT" > ./ENVIRONMENT.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n ./ENVIRONMENT.txt
|
echo -n ./build/env/ENVIRONMENT.txt
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
if [ "$GIT_BRANCH_AS_HASH" != 1 ]; then
|
if [ "$GIT_BRANCH_AS_HASH" != 1 ]; then
|
||||||
GIT_HASH="$(git rev-parse HEAD)$(if ! git diff-index --quiet HEAD --; then echo '-modified'; fi)"
|
GIT_HASH="$(git rev-parse HEAD)$(if ! git diff-index --quiet HEAD --; then echo '-modified'; fi)"
|
||||||
else
|
else
|
||||||
@@ -11,4 +13,4 @@ if ! [ -f ./GIT_HASH.txt ] || [ "$(cat ./GIT_HASH.txt)" != "$GIT_HASH" ]; then
|
|||||||
echo -n "$GIT_HASH" > ./GIT_HASH.txt
|
echo -n "$GIT_HASH" > ./GIT_HASH.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n ./GIT_HASH.txt
|
echo -n ./build/env/GIT_HASH.txt
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
if ! [ -f ./PLATFORM.txt ] || [ "$(cat ./PLATFORM.txt)" != "$PLATFORM" ] && [ -n "$PLATFORM" ]; then
|
if ! [ -f ./PLATFORM.txt ] || [ "$(cat ./PLATFORM.txt)" != "$PLATFORM" ] && [ -n "$PLATFORM" ]; then
|
||||||
>&2 echo "Updating PLATFORM.txt to \"$PLATFORM\""
|
>&2 echo "Updating PLATFORM.txt to \"$PLATFORM\""
|
||||||
echo -n "$PLATFORM" > ./PLATFORM.txt
|
echo -n "$PLATFORM" > ./PLATFORM.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n ./PLATFORM.txt
|
echo -n ./build/env/PLATFORM.txt
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
FE_VERSION="$(cat web/package.json | grep '"version"' | sed 's/[ \t]*"version":[ \t]*"\([^"]*\)",/\1/')"
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
FE_VERSION="$(cat ../../web/package.json | grep '"version"' | sed 's/[ \t]*"version":[ \t]*"\([^"]*\)",/\1/')"
|
||||||
|
|
||||||
# TODO: Validate other version sources - backend/Cargo.toml, backend/src/version/mod.rs
|
# TODO: Validate other version sources - backend/Cargo.toml, backend/src/version/mod.rs
|
||||||
|
|
||||||
@@ -10,4 +12,4 @@ if ! [ -f ./VERSION.txt ] || [ "$(cat ./VERSION.txt)" != "$VERSION" ]; then
|
|||||||
echo -n "$VERSION" > ./VERSION.txt
|
echo -n "$VERSION" > ./VERSION.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n ./VERSION.txt
|
echo -n ./build/env/VERSION.txt
|
||||||
@@ -73,7 +73,7 @@ if [ "$NON_FREE" = 1 ]; then
|
|||||||
if [ "$IB_SUITE" = "bullseye" ]; then
|
if [ "$IB_SUITE" = "bullseye" ]; then
|
||||||
ARCHIVE_AREAS="$ARCHIVE_AREAS non-free"
|
ARCHIVE_AREAS="$ARCHIVE_AREAS non-free"
|
||||||
else
|
else
|
||||||
ARCHIVE_AREAS="$ARCHIVE_AREAS non-free-firmware"
|
ARCHIVE_AREAS="$ARCHIVE_AREAS non-free non-free-firmware"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -86,6 +86,8 @@ if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|||||||
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours "rpi-v8 rpi-2712" )
|
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours "rpi-v8 rpi-2712" )
|
||||||
elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
||||||
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours rockchip64 )
|
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours rockchip64 )
|
||||||
|
elif [ "${IB_TARGET_ARCH}" = "riscv64" ]; then
|
||||||
|
PLATFORM_CONFIG_EXTRAS+=( --uefi-secure-boot=disable )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
@@ -152,9 +154,12 @@ prompt 0
|
|||||||
timeout 50
|
timeout 50
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cp $SOURCE_DIR/splash.png config/bootloaders/syslinux_common/splash.png
|
# Extract splash.png from the deb package
|
||||||
cp $SOURCE_DIR/splash.png config/bootloaders/isolinux/splash.png
|
dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xf - ./usr/lib/startos/splash.png > /tmp/splash.png
|
||||||
cp $SOURCE_DIR/splash.png config/bootloaders/grub-pc/splash.png
|
cp /tmp/splash.png config/bootloaders/syslinux_common/splash.png
|
||||||
|
cp /tmp/splash.png config/bootloaders/isolinux/splash.png
|
||||||
|
cp /tmp/splash.png config/bootloaders/grub-pc/splash.png
|
||||||
|
rm /tmp/splash.png
|
||||||
|
|
||||||
sed -i -e '2i set timeout=5' config/bootloaders/grub-pc/config.cfg
|
sed -i -e '2i set timeout=5' config/bootloaders/grub-pc/config.cfg
|
||||||
|
|
||||||
@@ -172,55 +177,151 @@ if [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
|||||||
echo "deb https://apt.armbian.com/ ${IB_SUITE} main" > config/archives/armbian.list
|
echo "deb https://apt.armbian.com/ ${IB_SUITE} main" > config/archives/armbian.list
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Dependencies
|
|
||||||
|
|
||||||
## Firmware
|
|
||||||
if [ "$NON_FREE" = 1 ]; then
|
if [ "$NON_FREE" = 1 ]; then
|
||||||
echo 'firmware-iwlwifi firmware-misc-nonfree firmware-brcm80211 firmware-realtek firmware-atheros firmware-libertas firmware-amd-graphics' > config/package-lists/nonfree.list.chroot
|
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o config/archives/nvidia-container-toolkit.key
|
||||||
|
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
|
||||||
|
| sed 's#deb https://#deb [signed-by=/etc/apt/trusted.gpg.d/nvidia-container-toolkit.key.gpg] https://#g' \
|
||||||
|
> config/archives/nvidia-container-toolkit.list
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
cat > config/archives/backports.pref <<-EOF
|
||||||
|
Package: linux-image-*
|
||||||
|
Pin: release n=${IB_SUITE}-backports
|
||||||
|
Pin-Priority: 500
|
||||||
|
|
||||||
|
Package: linux-headers-*
|
||||||
|
Pin: release n=${IB_SUITE}-backports
|
||||||
|
Pin-Priority: 500
|
||||||
|
|
||||||
|
Package: *nvidia*
|
||||||
|
Pin: release n=${IB_SUITE}-backports
|
||||||
|
Pin-Priority: 500
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Hooks
|
||||||
|
|
||||||
cat > config/hooks/normal/9000-install-startos.hook.chroot << EOF
|
cat > config/hooks/normal/9000-install-startos.hook.chroot << EOF
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
if [ "${NON_FREE}" = "1" ] && [ "${IB_TARGET_PLATFORM}" != "raspberrypi" ]; then
|
||||||
|
# install a specific NVIDIA driver version
|
||||||
|
|
||||||
|
# ---------------- configuration ----------------
|
||||||
|
NVIDIA_DRIVER_VERSION="\${NVIDIA_DRIVER_VERSION:-580.119.02}"
|
||||||
|
|
||||||
|
BASE_URL="https://download.nvidia.com/XFree86/Linux-${QEMU_ARCH}"
|
||||||
|
|
||||||
|
echo "[nvidia-hook] Using NVIDIA driver: \${NVIDIA_DRIVER_VERSION}" >&2
|
||||||
|
|
||||||
|
# ---------------- kernel version ----------------
|
||||||
|
|
||||||
|
# Determine target kernel version from newest /boot/vmlinuz-* in the chroot.
|
||||||
|
KVER="\$(
|
||||||
|
ls -1t /boot/vmlinuz-* 2>/dev/null \
|
||||||
|
| head -n1 \
|
||||||
|
| sed 's|.*/vmlinuz-||'
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [ -z "\${KVER}" ]; then
|
||||||
|
echo "[nvidia-hook] ERROR: no /boot/vmlinuz-* found; cannot determine kernel version" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[nvidia-hook] Target kernel version: \${KVER}" >&2
|
||||||
|
|
||||||
|
# Ensure kernel headers are present
|
||||||
|
TEMP_APT_DEPS=(build-essential)
|
||||||
|
if [ ! -e "/lib/modules/\${KVER}/build" ]; then
|
||||||
|
TEMP_APT_DEPS+=(linux-headers-\${KVER})
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[nvidia-hook] Installing build dependencies" >&2
|
||||||
|
|
||||||
|
/usr/lib/startos/scripts/install-equivs <<-EOF
|
||||||
|
Package: nvidia-depends
|
||||||
|
Version: \${NVIDIA_DRIVER_VERSION}
|
||||||
|
Section: unknown
|
||||||
|
Priority: optional
|
||||||
|
Depends: \${dep_list="\$(IFS=', '; echo "\${TEMP_APT_DEPS[*]}")"}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ---------------- download and run installer ----------------
|
||||||
|
|
||||||
|
RUN_NAME="NVIDIA-Linux-${QEMU_ARCH}-\${NVIDIA_DRIVER_VERSION}.run"
|
||||||
|
RUN_PATH="/root/\${RUN_NAME}"
|
||||||
|
RUN_URL="\${BASE_URL}/\${NVIDIA_DRIVER_VERSION}/\${RUN_NAME}"
|
||||||
|
|
||||||
|
echo "[nvidia-hook] Downloading \${RUN_URL}" >&2
|
||||||
|
wget -O "\${RUN_PATH}" "\${RUN_URL}"
|
||||||
|
chmod +x "\${RUN_PATH}"
|
||||||
|
|
||||||
|
echo "[nvidia-hook] Running NVIDIA installer for kernel \${KVER}" >&2
|
||||||
|
|
||||||
|
sh "\${RUN_PATH}" \
|
||||||
|
--silent \
|
||||||
|
--kernel-name="\${KVER}" \
|
||||||
|
--no-x-check \
|
||||||
|
--no-nouveau-check \
|
||||||
|
--no-runlevel-check
|
||||||
|
|
||||||
|
# Rebuild module metadata
|
||||||
|
echo "[nvidia-hook] Running depmod for \${KVER}" >&2
|
||||||
|
depmod -a "\${KVER}"
|
||||||
|
|
||||||
|
echo "[nvidia-hook] NVIDIA \${NVIDIA_DRIVER_VERSION} installation complete for kernel \${KVER}" >&2
|
||||||
|
|
||||||
|
echo "[nvidia-hook] Removing build dependencies..." >&2
|
||||||
|
apt-get purge -y nvidia-depends
|
||||||
|
apt-get autoremove -y
|
||||||
|
echo "[nvidia-hook] Removed build dependencies." >&2
|
||||||
|
fi
|
||||||
|
|
||||||
cp /etc/resolv.conf /etc/resolv.conf.bak
|
cp /etc/resolv.conf /etc/resolv.conf.bak
|
||||||
|
|
||||||
if [ "${IB_SUITE}" = trixie ] && [ "${IB_PLATFORM}" != riscv64 ]; then
|
if [ "${IB_SUITE}" = trixie ] && [ "${IB_TARGET_ARCH}" != riscv64 ]; then
|
||||||
echo 'deb https://deb.debian.org/debian/ bookworm main' > /etc/apt/sources.list.d/bookworm.list
|
echo 'deb https://deb.debian.org/debian/ bookworm main' > /etc/apt/sources.list.d/bookworm.list
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y postgresql-15
|
apt-get install -y postgresql-15
|
||||||
rm /etc/apt/sources.list.d/bookworm.list
|
rm /etc/apt/sources.list.d/bookworm.list
|
||||||
apt-get update
|
apt-get update
|
||||||
systemctl mask postgresql
|
systemctl mask postgresql
|
||||||
fi
|
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
|
||||||
KERNEL_VERSION=${RPI_KERNEL_VERSION} sh /boot/config.sh > /boot/config.txt
|
KERNEL_VERSION=${RPI_KERNEL_VERSION} sh /boot/config.sh > /boot/config.txt
|
||||||
mkinitramfs -c gzip -o 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 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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
useradd --shell /bin/bash -G startos -m start9
|
useradd --shell /bin/bash -G startos -m start9
|
||||||
echo start9:embassy | chpasswd
|
echo start9:embassy | chpasswd
|
||||||
usermod -aG sudo start9
|
usermod -aG sudo start9
|
||||||
|
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
|
if [ "${IB_TARGET_PLATFORM}" != "raspberrypi" ]; then
|
||||||
/usr/lib/startos/scripts/enable-kiosk
|
/usr/lib/startos/scripts/enable-kiosk
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then
|
if ! [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then
|
||||||
passwd -l start9
|
passwd -l start9
|
||||||
fi
|
fi
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}"
|
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}"
|
||||||
|
|
||||||
lb bootstrap
|
if lb bootstrap; then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
EXIT=$?
|
||||||
|
cat ./chroot/debootstrap/debootstrap.log
|
||||||
|
exit $EXIT
|
||||||
|
fi
|
||||||
lb chroot
|
lb chroot
|
||||||
lb installer
|
lb installer
|
||||||
lb binary_chroot
|
lb binary_chroot
|
||||||
@@ -345,4 +446,4 @@ elif [ "${IMAGE_TYPE}" = img ]; then
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
chown $IB_UID:$IB_UID $RESULTS_DIR/$IMAGE_BASENAME.*
|
chown $IB_UID:$IB_UID $RESULTS_DIR/$IMAGE_BASENAME.*
|
||||||
@@ -1 +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 quiet boot=startos
|
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
|
||||||
35
build/image-recipe/run-local-build.sh
Executable file
35
build/image-recipe/run-local-build.sh
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
|
||||||
|
|
||||||
|
BASEDIR="$(pwd -P)"
|
||||||
|
|
||||||
|
SUITE=trixie
|
||||||
|
|
||||||
|
USE_TTY=
|
||||||
|
if tty -s; then
|
||||||
|
USE_TTY="-it"
|
||||||
|
fi
|
||||||
|
|
||||||
|
dockerfile_hash=$(sha256sum ${BASEDIR}/build/image-recipe/Dockerfile | head -c 7)
|
||||||
|
|
||||||
|
docker_img_name="start9/build-iso:${SUITE}-${dockerfile_hash}"
|
||||||
|
|
||||||
|
platform=linux/${ARCH}
|
||||||
|
case $ARCH in
|
||||||
|
x86_64)
|
||||||
|
platform=linux/amd64;;
|
||||||
|
aarch64)
|
||||||
|
platform=linux/arm64;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if ! docker run --rm --platform=$platform "${docker_img_name}" true 2> /dev/null; then
|
||||||
|
docker buildx build --load --platform=$platform --build-arg=SUITE=${SUITE} -t "${docker_img_name}" ./build/image-recipe
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker run $USE_TTY --rm --platform=$platform --privileged -v "$(pwd)/build/image-recipe:/root/image-recipe" -v "$(pwd)/results:/root/results" \
|
||||||
|
-e IB_SUITE="$SUITE" \
|
||||||
|
-e IB_UID="$UID" \
|
||||||
|
-e IB_INCLUDE \
|
||||||
|
"${docker_img_name}" /root/image-recipe/build.sh $@
|
||||||
51
build/lib/grub-theme/theme.txt
Normal file
51
build/lib/grub-theme/theme.txt
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
desktop-image: "../splash.png"
|
||||||
|
title-color: "#ffffff"
|
||||||
|
title-font: "Unifont Regular 16"
|
||||||
|
title-text: "StartOS Boot Menu with GRUB"
|
||||||
|
message-font: "Unifont Regular 16"
|
||||||
|
terminal-font: "Unifont Regular 16"
|
||||||
|
|
||||||
|
#help bar at the bottom
|
||||||
|
+ label {
|
||||||
|
top = 100%-50
|
||||||
|
left = 0
|
||||||
|
width = 100%
|
||||||
|
height = 20
|
||||||
|
text = "@KEYMAP_SHORT@"
|
||||||
|
align = "center"
|
||||||
|
color = "#ffffff"
|
||||||
|
font = "Unifont Regular 16"
|
||||||
|
}
|
||||||
|
|
||||||
|
#boot menu
|
||||||
|
+ boot_menu {
|
||||||
|
left = 10%
|
||||||
|
width = 80%
|
||||||
|
top = 52%
|
||||||
|
height = 48%-80
|
||||||
|
item_color = "#a8a8a8"
|
||||||
|
item_font = "Unifont Regular 16"
|
||||||
|
selected_item_color= "#ffffff"
|
||||||
|
selected_item_font = "Unifont Regular 16"
|
||||||
|
item_height = 16
|
||||||
|
item_padding = 0
|
||||||
|
item_spacing = 4
|
||||||
|
icon_width = 0
|
||||||
|
icon_heigh = 0
|
||||||
|
item_icon_space = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress bar
|
||||||
|
+ progress_bar {
|
||||||
|
id = "__timeout__"
|
||||||
|
left = 15%
|
||||||
|
top = 100%-80
|
||||||
|
height = 16
|
||||||
|
width = 70%
|
||||||
|
font = "Unifont Regular 16"
|
||||||
|
text_color = "#000000"
|
||||||
|
fg_color = "#ffffff"
|
||||||
|
bg_color = "#a8a8a8"
|
||||||
|
border_color = "#ffffff"
|
||||||
|
text = "@TIMEOUT_NOTIFICATION_LONG@"
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ parse_essential_db_info() {
|
|||||||
DB_DUMP="/tmp/startos_db.json"
|
DB_DUMP="/tmp/startos_db.json"
|
||||||
|
|
||||||
if command -v start-cli >/dev/null 2>&1; then
|
if command -v start-cli >/dev/null 2>&1; then
|
||||||
start-cli db dump > "$DB_DUMP" 2>/dev/null || return 1
|
timeout 30 start-cli db dump > "$DB_DUMP" 2>/dev/null || return 1
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -22,7 +22,7 @@ parse_essential_db_info() {
|
|||||||
RAM_GB="unknown"
|
RAM_GB="unknown"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RUNNING_SERVICES=$(jq -r '[.value.packageData[] | select(.status.main == "running")] | length' "$DB_DUMP" 2>/dev/null)
|
RUNNING_SERVICES=$(jq -r '[.value.packageData[] | select(.statusInfo.started != null)] | length' "$DB_DUMP" 2>/dev/null)
|
||||||
TOTAL_SERVICES=$(jq -r '.value.packageData | length' "$DB_DUMP" 2>/dev/null)
|
TOTAL_SERVICES=$(jq -r '.value.packageData | length' "$DB_DUMP" 2>/dev/null)
|
||||||
|
|
||||||
rm -f "$DB_DUMP"
|
rm -f "$DB_DUMP"
|
||||||
|
|||||||
@@ -10,24 +10,24 @@ fi
|
|||||||
POSITIONAL_ARGS=()
|
POSITIONAL_ARGS=()
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
--no-sync)
|
--no-sync)
|
||||||
NO_SYNC=1
|
NO_SYNC=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--create)
|
--create)
|
||||||
ONLY_CREATE=1
|
ONLY_CREATE=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-*|--*)
|
-*|--*)
|
||||||
echo "Unknown option $1"
|
echo "Unknown option $1"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
POSITIONAL_ARGS+=("$1") # save positional arg
|
POSITIONAL_ARGS+=("$1") # save positional arg
|
||||||
shift # past argument
|
shift # past argument
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
|
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
|
||||||
@@ -35,7 +35,7 @@ set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
|
|||||||
if [ -z "$NO_SYNC" ]; then
|
if [ -z "$NO_SYNC" ]; then
|
||||||
echo 'Syncing...'
|
echo 'Syncing...'
|
||||||
umount -R /media/startos/next 2> /dev/null
|
umount -R /media/startos/next 2> /dev/null
|
||||||
umount -R /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
|
||||||
mount -t tmpfs tmpfs /media/startos/upper
|
mount -t tmpfs tmpfs /media/startos/upper
|
||||||
@@ -43,8 +43,6 @@ if [ -z "$NO_SYNC" ]; then
|
|||||||
mount -t overlay \
|
mount -t overlay \
|
||||||
-olowerdir=/media/startos/current,upperdir=/media/startos/upper/data,workdir=/media/startos/upper/work \
|
-olowerdir=/media/startos/current,upperdir=/media/startos/upper/data,workdir=/media/startos/upper/work \
|
||||||
overlay /media/startos/next
|
overlay /media/startos/next
|
||||||
mkdir -p /media/startos/next/media/startos/root
|
|
||||||
mount --bind /media/startos/root /media/startos/next/media/startos/root
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$ONLY_CREATE" ]; then
|
if [ -n "$ONLY_CREATE" ]; then
|
||||||
@@ -56,12 +54,18 @@ mkdir -p /media/startos/next/dev
|
|||||||
mkdir -p /media/startos/next/sys
|
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
|
||||||
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 --bind /sys /media/startos/next/sys
|
mount --bind /sys /media/startos/next/sys
|
||||||
mount --bind /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
|
||||||
|
|
||||||
|
if mountpoint /sys/firmware/efi/efivars 2>&1 > /dev/null; then
|
||||||
|
mount --bind /sys/firmware/efi/efivars /media/startos/next/sys/firmware/efi/efivars
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$*" ]; then
|
if [ -z "$*" ]; then
|
||||||
chroot /media/startos/next
|
chroot /media/startos/next
|
||||||
@@ -71,6 +75,10 @@ else
|
|||||||
CHROOT_RES=$?
|
CHROOT_RES=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if mountpoint /media/startos/next/sys/firmware/efi/efivars 2>&1 > /dev/null; then
|
||||||
|
umount /media/startos/next/sys/firmware/efi/efivars
|
||||||
|
fi
|
||||||
|
|
||||||
umount /media/startos/next/run
|
umount /media/startos/next/run
|
||||||
umount /media/startos/next/tmp
|
umount /media/startos/next/tmp
|
||||||
umount /media/startos/next/dev
|
umount /media/startos/next/dev
|
||||||
@@ -87,11 +95,12 @@ if [ "$CHROOT_RES" -eq 0 ]; then
|
|||||||
|
|
||||||
echo 'Upgrading...'
|
echo 'Upgrading...'
|
||||||
|
|
||||||
|
rm -f /media/startos/images/next.squashfs
|
||||||
if ! time mksquashfs /media/startos/next /media/startos/images/next.squashfs -b 4096 -comp gzip; then
|
if ! time mksquashfs /media/startos/next /media/startos/images/next.squashfs -b 4096 -comp gzip; then
|
||||||
umount -R /media/startos/next
|
umount -l /media/startos/next
|
||||||
umount -R /media/startos/upper
|
umount -l /media/startos/upper
|
||||||
rm -rf /media/startos/upper /media/startos/next
|
rm -rf /media/startos/upper /media/startos/next
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
hash=$(b3sum /media/startos/images/next.squashfs | head -c 32)
|
hash=$(b3sum /media/startos/images/next.squashfs | head -c 32)
|
||||||
mv /media/startos/images/next.squashfs /media/startos/images/${hash}.rootfs
|
mv /media/startos/images/next.squashfs /media/startos/images/${hash}.rootfs
|
||||||
@@ -103,5 +112,5 @@ if [ "$CHROOT_RES" -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
umount -R /media/startos/next
|
umount -R /media/startos/next
|
||||||
umount -R /media/startos/upper
|
umount /media/startos/upper
|
||||||
rm -rf /media/startos/upper /media/startos/next
|
rm -rf /media/startos/upper /media/startos/next
|
||||||
@@ -1,38 +1,55 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ -z "$sip" ] || [ -z "$dip" ] || [ -z "$sport" ] || [ -z "$dport" ]; then
|
if [ -z "$sip" ] || [ -z "$dip" ] || [ -z "$dprefix" ] || [ -z "$sport" ] || [ -z "$dport" ]; then
|
||||||
>&2 echo 'missing required env var'
|
>&2 echo 'missing required env var'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Helper function to check if a rule exists
|
NAME="F$(echo "$sip:$sport -> $dip/$dprefix:$dport" | sha256sum | head -c 15)"
|
||||||
nat_rule_exists() {
|
|
||||||
iptables -t nat -C "$@" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Helper function to add or delete a rule idempotently
|
for kind in INPUT FORWARD ACCEPT; do
|
||||||
# Usage: apply_rule [add|del] <iptables args...>
|
if ! iptables -C $kind -j "${NAME}_${kind}" 2> /dev/null; then
|
||||||
apply_nat_rule() {
|
iptables -N "${NAME}_${kind}" 2> /dev/null
|
||||||
local action="$1"
|
iptables -A $kind -j "${NAME}_${kind}"
|
||||||
shift
|
|
||||||
|
|
||||||
if [ "$action" = "add" ]; then
|
|
||||||
# Only add if rule doesn't exist
|
|
||||||
if ! rule_exists "$@"; then
|
|
||||||
iptables -t nat -A "$@"
|
|
||||||
fi
|
|
||||||
elif [ "$action" = "del" ]; then
|
|
||||||
if rule_exists "$@"; then
|
|
||||||
iptables -t nat -D "$@"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
}
|
done
|
||||||
|
for kind in PREROUTING INPUT OUTPUT POSTROUTING; do
|
||||||
|
if ! iptables -t nat -C $kind -j "${NAME}_${kind}" 2> /dev/null; then
|
||||||
|
iptables -t nat -N "${NAME}_${kind}" 2> /dev/null
|
||||||
|
iptables -t nat -A $kind -j "${NAME}_${kind}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
err=0
|
||||||
|
trap 'err=1' ERR
|
||||||
|
|
||||||
|
for kind in INPUT FORWARD ACCEPT; do
|
||||||
|
iptables -F "${NAME}_${kind}" 2> /dev/null
|
||||||
|
done
|
||||||
|
for kind in PREROUTING INPUT OUTPUT POSTROUTING; do
|
||||||
|
iptables -t nat -F "${NAME}_${kind}" 2> /dev/null
|
||||||
|
done
|
||||||
if [ "$UNDO" = 1 ]; then
|
if [ "$UNDO" = 1 ]; then
|
||||||
action="del"
|
conntrack -D -p tcp -d $sip --dport $sport || true # conntrack returns exit 1 if no connections are active
|
||||||
else
|
conntrack -D -p udp -d $sip --dport $sport || true # conntrack returns exit 1 if no connections are active
|
||||||
action="add"
|
exit $err
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apply_nat_rule "$action" PREROUTING -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport
|
# DNAT: rewrite destination for incoming packets (external traffic)
|
||||||
apply_nat_rule "$action" OUTPUT -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport
|
iptables -t nat -A ${NAME}_PREROUTING -d "$sip" -p tcp --dport "$sport" -j DNAT --to-destination "$dip:$dport"
|
||||||
|
iptables -t nat -A ${NAME}_PREROUTING -d "$sip" -p udp --dport "$sport" -j DNAT --to-destination "$dip:$dport"
|
||||||
|
|
||||||
|
# DNAT: rewrite destination for locally-originated packets (hairpin from host itself)
|
||||||
|
iptables -t nat -A ${NAME}_OUTPUT -d "$sip" -p tcp --dport "$sport" -j DNAT --to-destination "$dip:$dport"
|
||||||
|
iptables -t nat -A ${NAME}_OUTPUT -d "$sip" -p udp --dport "$sport" -j DNAT --to-destination "$dip:$dport"
|
||||||
|
|
||||||
|
# MASQUERADE: rewrite source for all forwarded traffic to the destination
|
||||||
|
# This ensures responses are routed back through the host regardless of source IP
|
||||||
|
iptables -t nat -A ${NAME}_POSTROUTING -d "$dip" -p tcp --dport "$dport" -j MASQUERADE
|
||||||
|
iptables -t nat -A ${NAME}_POSTROUTING -d "$dip" -p udp --dport "$dport" -j MASQUERADE
|
||||||
|
|
||||||
|
# Allow new connections to be forwarded to the destination
|
||||||
|
iptables -A ${NAME}_FORWARD -d $dip -p tcp --dport $dport -m state --state NEW -j ACCEPT
|
||||||
|
iptables -A ${NAME}_FORWARD -d $dip -p udp --dport $dport -m state --state NEW -j ACCEPT
|
||||||
|
|
||||||
|
exit $err
|
||||||
20
build/lib/scripts/install-equivs
Executable file
20
build/lib/scripts/install-equivs
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
export DEBCONF_NONINTERACTIVE_SEEN=true
|
||||||
|
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
cd $TMP_DIR
|
||||||
|
|
||||||
|
cat > control.equivs
|
||||||
|
equivs-build control.equivs
|
||||||
|
apt-get install -y ./*.deb < /dev/null
|
||||||
|
)
|
||||||
|
|
||||||
|
rm -rf $TMP_DIR
|
||||||
|
|
||||||
|
echo Install complete. >&2
|
||||||
|
exit 0
|
||||||
@@ -29,10 +29,13 @@ if [ -z "$needed" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
MARGIN=${MARGIN:-1073741824}
|
||||||
|
target=$((needed + MARGIN))
|
||||||
|
|
||||||
if [ -h /media/startos/config/current.rootfs ] && [ -e /media/startos/config/current.rootfs ]; then
|
if [ -h /media/startos/config/current.rootfs ] && [ -e /media/startos/config/current.rootfs ]; then
|
||||||
echo 'Pruning...'
|
echo 'Pruning...'
|
||||||
current="$(readlink -f /media/startos/config/current.rootfs)"
|
current="$(readlink -f /media/startos/config/current.rootfs)"
|
||||||
while [[ "$(df -B1 --output=avail --sync /media/startos/images | tail -n1)" -lt "$needed" ]]; do
|
while [[ "$(df -B1 --output=avail --sync /media/startos/images | tail -n1)" -lt "$target" ]]; do
|
||||||
to_prune="$(ls -t1 /media/startos/images/*.rootfs /media/startos/images/*.squashfs 2> /dev/null | grep -v "$current" | tail -n1)"
|
to_prune="$(ls -t1 /media/startos/images/*.rootfs /media/startos/images/*.squashfs 2> /dev/null | grep -v "$current" | tail -n1)"
|
||||||
if [ -e "$to_prune" ]; then
|
if [ -e "$to_prune" ]; then
|
||||||
echo " Pruning $to_prune"
|
echo " Pruning $to_prune"
|
||||||
|
|||||||
@@ -1,36 +1,64 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
fail=$(printf " [\033[31m fail \033[0m]")
|
# --- Config ---
|
||||||
pass=$(printf " [\033[32m pass \033[0m]")
|
# Colors (using printf to ensure compatibility)
|
||||||
|
GRAY=$(printf '\033[90m')
|
||||||
|
GREEN=$(printf '\033[32m')
|
||||||
|
RED=$(printf '\033[31m')
|
||||||
|
NC=$(printf '\033[0m') # No Color
|
||||||
|
|
||||||
|
# Proxies to test
|
||||||
|
proxies=(
|
||||||
|
"Host Tor|127.0.1.1:9050"
|
||||||
|
"Startd Tor|10.0.3.1:9050"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Default URLs
|
||||||
onion_list=(
|
onion_list=(
|
||||||
|
"The Tor Project|http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion"
|
||||||
"Start9|http://privacy34kn4ez3y3nijweec6w4g54i3g54sdv7r5mr6soma3w4begyd.onion"
|
"Start9|http://privacy34kn4ez3y3nijweec6w4g54i3g54sdv7r5mr6soma3w4begyd.onion"
|
||||||
"Mempool|http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion"
|
"Mempool|http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion"
|
||||||
"DuckDuckGo|https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion"
|
"DuckDuckGo|https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion"
|
||||||
"Brave Search|https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion"
|
"Brave Search|https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if ~/.startos/tor-check.list exists and read its contents if available
|
# Load custom list
|
||||||
if [ -f ~/.startos/tor-check.list ]; then
|
[ -f ~/.startos/tor-check.list ] && readarray -t custom_list < <(grep -v '^#' ~/.startos/tor-check.list) && onion_list+=("${custom_list[@]}")
|
||||||
while IFS= read -r line; do
|
|
||||||
# Check if the line starts with a #
|
# --- Functions ---
|
||||||
if [[ ! "$line" =~ ^# ]]; then
|
print_line() { printf "${GRAY}────────────────────────────────────────${NC}\n"; }
|
||||||
onion_list+=("$line")
|
|
||||||
|
# --- Main ---
|
||||||
|
echo "Testing Onion Connections..."
|
||||||
|
|
||||||
|
for proxy_info in "${proxies[@]}"; do
|
||||||
|
proxy_name="${proxy_info%%|*}"
|
||||||
|
proxy_addr="${proxy_info#*|}"
|
||||||
|
|
||||||
|
print_line
|
||||||
|
printf "${GRAY}Proxy: %s (%s)${NC}\n" "$proxy_name" "$proxy_addr"
|
||||||
|
|
||||||
|
for data in "${onion_list[@]}"; do
|
||||||
|
name="${data%%|*}"
|
||||||
|
url="${data#*|}"
|
||||||
|
|
||||||
|
# Capture verbose output + http code.
|
||||||
|
# --no-progress-meter: Suppresses the "0 0 0" stats but keeps -v output
|
||||||
|
output=$(curl -v --no-progress-meter --max-time 15 --socks5-hostname "$proxy_addr" "$url" 2>&1)
|
||||||
|
exit_code=$?
|
||||||
|
|
||||||
|
if [ $exit_code -eq 0 ]; then
|
||||||
|
printf " ${GREEN}[pass]${NC} %s (%s)\n" "$name" "$url"
|
||||||
|
else
|
||||||
|
printf " ${RED}[fail]${NC} %s (%s)\n" "$name" "$url"
|
||||||
|
printf " ${RED}↳ Curl Error %s${NC}\n" "$exit_code"
|
||||||
|
|
||||||
|
# Print the last 4 lines of verbose log to show the specific handshake error
|
||||||
|
# We look for lines starting with '*' or '>' or '<' to filter out junk if any remains
|
||||||
|
echo "$output" | tail -n 4 | sed "s/^/ ${GRAY}/"
|
||||||
fi
|
fi
|
||||||
done < ~/.startos/tor-check.list
|
done
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Testing connection to Onion Pages ..."
|
|
||||||
|
|
||||||
for data in "${onion_list[@]}"; do
|
|
||||||
name="${data%%|*}"
|
|
||||||
url="${data#*|}"
|
|
||||||
if curl --socks5-hostname localhost:9050 "$url" > /dev/null 2>&1; then
|
|
||||||
echo " ${pass}: $name ($url) "
|
|
||||||
else
|
|
||||||
echo " ${fail}: $name ($url) "
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
print_line
|
||||||
echo
|
# Reset color just in case
|
||||||
echo "Done."
|
printf "${NC}"
|
||||||
|
|||||||
82
build/lib/scripts/upgrade
Executable file
82
build/lib/scripts/upgrade
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SOURCE_DIR="$(dirname $(realpath "${BASH_SOURCE[0]}"))"
|
||||||
|
|
||||||
|
if [ "$UID" -ne 0 ]; then
|
||||||
|
>&2 echo 'Must be run as root'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -f "$1" ]; then
|
||||||
|
>&2 echo "usage: $0 <SQUASHFS>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'Upgrading...'
|
||||||
|
|
||||||
|
hash=$(b3sum $1 | head -c 32)
|
||||||
|
if [ -n "$2" ] && [ "$hash" != "$CHECKSUM" ]; then
|
||||||
|
>&2 echo 'Checksum mismatch'
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
unsquashfs -f -d / $1 boot
|
||||||
|
|
||||||
|
umount -R /media/startos/next 2> /dev/null || true
|
||||||
|
umount /media/startos/upper 2> /dev/null || true
|
||||||
|
umount /media/startos/lower 2> /dev/null || true
|
||||||
|
|
||||||
|
mkdir -p /media/startos/upper
|
||||||
|
mount -t tmpfs tmpfs /media/startos/upper
|
||||||
|
mkdir -p /media/startos/lower /media/startos/upper/data /media/startos/upper/work /media/startos/next
|
||||||
|
mount $1 /media/startos/lower
|
||||||
|
mount -t overlay \
|
||||||
|
-olowerdir=/media/startos/lower,upperdir=/media/startos/upper/data,workdir=/media/startos/upper/work \
|
||||||
|
overlay /media/startos/next
|
||||||
|
|
||||||
|
mkdir -p /media/startos/next/run
|
||||||
|
mkdir -p /media/startos/next/dev
|
||||||
|
mkdir -p /media/startos/next/sys
|
||||||
|
mkdir -p /media/startos/next/proc
|
||||||
|
mkdir -p /media/startos/next/boot
|
||||||
|
mkdir -p /media/startos/next/media/startos/root
|
||||||
|
mount --bind /run /media/startos/next/run
|
||||||
|
mount --bind /tmp /media/startos/next/tmp
|
||||||
|
mount --bind /dev /media/startos/next/dev
|
||||||
|
mount --bind /sys /media/startos/next/sys
|
||||||
|
mount --bind /proc /media/startos/next/proc
|
||||||
|
mount --bind /boot /media/startos/next/boot
|
||||||
|
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
|
||||||
|
mount --bind /sys/firmware/efi/efivars /media/startos/next/sys/firmware/efi/efivars
|
||||||
|
fi
|
||||||
|
|
||||||
|
chroot /media/startos/next bash -e << "EOF"
|
||||||
|
|
||||||
|
if [ -f /boot/grub/grub.cfg ]; then
|
||||||
|
grub-install /dev/$(eval $(lsblk -o MOUNTPOINT,PKNAME -P | grep 'MOUNTPOINT="/media/startos/root"') && echo $PKNAME)
|
||||||
|
update-grub
|
||||||
|
fi
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sync
|
||||||
|
|
||||||
|
umount -Rl /media/startos/next
|
||||||
|
umount /media/startos/upper
|
||||||
|
umount /media/startos/lower
|
||||||
|
|
||||||
|
mv $1 /media/startos/images/${hash}.rootfs
|
||||||
|
ln -rsf /media/startos/images/${hash}.rootfs /media/startos/config/current.rootfs
|
||||||
|
|
||||||
|
sync
|
||||||
|
|
||||||
|
echo 'System upgrade complete. Reboot to apply changes...'
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ "$UID" -ne 0 ]; then
|
|
||||||
>&2 echo 'Must be run as root'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
>&2 echo "usage: $0 <SQUASHFS>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION=$(unsquashfs -cat $1 /usr/lib/startos/VERSION.txt)
|
|
||||||
GIT_HASH=$(unsquashfs -cat $1 /usr/lib/startos/GIT_HASH.txt)
|
|
||||||
B3SUM=$(b3sum $1 | head -c 32)
|
|
||||||
|
|
||||||
if [ -n "$CHECKSUM" ] && [ "$CHECKSUM" != "$B3SUM" ]; then
|
|
||||||
>&2 echo "CHECKSUM MISMATCH"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
mv $1 /media/startos/images/${B3SUM}.rootfs
|
|
||||||
ln -rsf /media/startos/images/${B3SUM}.rootfs /media/startos/config/current.rootfs
|
|
||||||
|
|
||||||
unsquashfs -n -f -d / /media/startos/images/${B3SUM}.rootfs boot
|
|
||||||
|
|
||||||
umount -R /media/startos/next 2> /dev/null || true
|
|
||||||
umount -R /media/startos/lower 2> /dev/null || true
|
|
||||||
umount -R /media/startos/upper 2> /dev/null || true
|
|
||||||
|
|
||||||
rm -rf /media/startos/lower /media/startos/upper /media/startos/next
|
|
||||||
mkdir /media/startos/upper
|
|
||||||
mount -t tmpfs tmpfs /media/startos/upper
|
|
||||||
mkdir -p /media/startos/lower /media/startos/upper/data /media/startos/upper/work /media/startos/next
|
|
||||||
mount /media/startos/images/${B3SUM}.rootfs /media/startos/lower
|
|
||||||
mount -t overlay \
|
|
||||||
-olowerdir=/media/startos/lower,upperdir=/media/startos/upper/data,workdir=/media/startos/upper/work \
|
|
||||||
overlay /media/startos/next
|
|
||||||
mkdir -p /media/startos/next/media/startos/root
|
|
||||||
mount --bind /media/startos/root /media/startos/next/media/startos/root
|
|
||||||
mkdir -p /media/startos/next/dev
|
|
||||||
mkdir -p /media/startos/next/sys
|
|
||||||
mkdir -p /media/startos/next/proc
|
|
||||||
mkdir -p /media/startos/next/boot
|
|
||||||
mount --bind /dev /media/startos/next/dev
|
|
||||||
mount --bind /sys /media/startos/next/sys
|
|
||||||
mount --bind /proc /media/startos/next/proc
|
|
||||||
mount --bind /boot /media/startos/next/boot
|
|
||||||
|
|
||||||
chroot /media/startos/next update-grub2
|
|
||||||
|
|
||||||
umount -R /media/startos/next
|
|
||||||
umount -R /media/startos/upper
|
|
||||||
umount -R /media/startos/lower
|
|
||||||
rm -rf /media/startos/lower /media/startos/upper /media/startos/next
|
|
||||||
|
|
||||||
sync
|
|
||||||
|
|
||||||
reboot
|
|
||||||
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
@@ -1,4 +1,4 @@
|
|||||||
FROM debian:bookworm
|
FROM debian:trixie
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
@@ -12,45 +12,14 @@ RUN apt-get update && \
|
|||||||
jq \
|
jq \
|
||||||
gzip \
|
gzip \
|
||||||
brotli \
|
brotli \
|
||||||
qemu-user-static \
|
|
||||||
binfmt-support \
|
|
||||||
squashfs-tools \
|
squashfs-tools \
|
||||||
git \
|
git \
|
||||||
debspawn \
|
|
||||||
rsync \
|
rsync \
|
||||||
b3sum \
|
b3sum \
|
||||||
fuse-overlayfs \
|
|
||||||
sudo \
|
sudo \
|
||||||
systemd \
|
nodejs
|
||||||
systemd-container \
|
|
||||||
systemd-sysv \
|
|
||||||
dbus \
|
|
||||||
dbus-user-session
|
|
||||||
|
|
||||||
RUN systemctl mask \
|
|
||||||
systemd-firstboot.service \
|
|
||||||
systemd-udevd.service \
|
|
||||||
getty@tty1.service \
|
|
||||||
console-getty.service
|
|
||||||
|
|
||||||
RUN git config --global --add safe.directory /root/start-os
|
RUN git config --global --add safe.directory /root/start-os
|
||||||
|
|
||||||
RUN mkdir -p /etc/debspawn && \
|
|
||||||
echo "AllowUnsafePermissions=true" > /etc/debspawn/global.toml
|
|
||||||
|
|
||||||
ENV NVM_DIR=~/.nvm
|
|
||||||
ENV NODE_VERSION=22
|
|
||||||
RUN mkdir -p $NVM_DIR && \
|
|
||||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash && \
|
|
||||||
. $NVM_DIR/nvm.sh \
|
|
||||||
nvm install $NODE_VERSION && \
|
|
||||||
nvm use $NODE_VERSION && \
|
|
||||||
nvm alias default $NODE_VERSION && \
|
|
||||||
ln -s $(which node) /usr/bin/node && \
|
|
||||||
ln -s $(which npm) /usr/bin/npm
|
|
||||||
|
|
||||||
RUN mkdir -p /root/start-os
|
RUN mkdir -p /root/start-os
|
||||||
WORKDIR /root/start-os
|
WORKDIR /root/start-os
|
||||||
|
|
||||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
|
||||||
ENTRYPOINT [ "/docker-entrypoint.sh" ]
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
exec /lib/systemd/systemd --unit=multi-user.target --show-status=false --log-target=journal
|
|
||||||
@@ -1,27 +1,30 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ "$FORCE_COMPAT" = 1 ] || ( [ "$REQUIRES" = "linux" ] && [ "$(uname -s)" != "Linux" ] ) || ( [ "$REQUIRES" = "debian" ] && ! which dpkg > /dev/null ); then
|
pwd=$(pwd)
|
||||||
project_pwd="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd)/"
|
|
||||||
pwd="$(pwd)/"
|
|
||||||
if ! [[ "$pwd" = "$project_pwd"* ]]; then
|
|
||||||
>&2 echo "Must be run from start-os project dir"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
rel_pwd="${pwd#"$project_pwd"}"
|
|
||||||
|
|
||||||
SYSTEMD_TTY="-P"
|
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
|
||||||
USE_TTY=
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
rel_pwd="${pwd#"$(pwd)"}"
|
||||||
|
|
||||||
|
COMPAT_ARCH=$(uname -m)
|
||||||
|
|
||||||
|
platform=linux/$COMPAT_ARCH
|
||||||
|
|
||||||
|
case $COMPAT_ARCH in
|
||||||
|
x86_64)
|
||||||
|
platform=linux/amd64;;
|
||||||
|
aarch64)
|
||||||
|
platform=linux/arm64;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$FORCE_COMPAT" = 1 ] || ( [ "$REQUIRES" = "linux" ] && [ "$(uname -s)" != "Linux" ] ) || ( [ "$REQUIRES" = "debian" ] && ! which dpkg > /dev/null ); then
|
||||||
if tty -s; then
|
if tty -s; then
|
||||||
USE_TTY="-it"
|
USE_TTY="-it"
|
||||||
SYSTEMD_TTY="-t"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker run -d --rm --name os-compat --privileged --security-opt apparmor=unconfined -v "${project_pwd}:/root/start-os" -v /lib/modules:/lib/modules:ro start9/build-env
|
docker run $USE_TTY --platform=$platform -eARCH -eENVIRONMENT -ePLATFORM -eGIT_BRANCH_AS_HASH -ePROJECT -eDEPENDS -eCONFLICTS -w "/root/start-os${rel_pwd}" --rm -v "$(pwd):/root/start-os" start9/build-env $@
|
||||||
while ! docker exec os-compat systemctl is-active --quiet multi-user.target 2> /dev/null; do sleep .5; done
|
|
||||||
docker exec -eARCH -eENVIRONMENT -ePLATFORM -eGIT_BRANCH_AS_HASH -ePROJECT -eDEPENDS -eCONFLICTS $USE_TTY -w "/root/start-os${rel_pwd}" os-compat $@
|
|
||||||
code=$?
|
|
||||||
docker stop os-compat
|
|
||||||
exit $code
|
|
||||||
else
|
else
|
||||||
exec $@
|
exec $@
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
function partition_for () {
|
|
||||||
if [[ "$1" =~ [0-9]+$ ]]; then
|
|
||||||
echo "$1p$2"
|
|
||||||
else
|
|
||||||
echo "$1$2"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSION=$(cat VERSION.txt)
|
|
||||||
ENVIRONMENT=$(cat ENVIRONMENT.txt)
|
|
||||||
GIT_HASH=$(cat GIT_HASH.txt | head -c 7)
|
|
||||||
DATE=$(date +%Y%m%d)
|
|
||||||
|
|
||||||
ROOT_PART_END=7217792
|
|
||||||
|
|
||||||
VERSION_FULL="$VERSION-$GIT_HASH"
|
|
||||||
|
|
||||||
if [ -n "$ENVIRONMENT" ]; then
|
|
||||||
VERSION_FULL="$VERSION_FULL~$ENVIRONMENT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
TARGET_NAME=startos-${VERSION_FULL}-${DATE}_raspberrypi.img
|
|
||||||
TARGET_SIZE=$[($ROOT_PART_END+1)*512]
|
|
||||||
|
|
||||||
rm -f $TARGET_NAME
|
|
||||||
truncate -s $TARGET_SIZE $TARGET_NAME
|
|
||||||
(
|
|
||||||
echo o
|
|
||||||
echo x
|
|
||||||
echo i
|
|
||||||
echo "0xcb15ae4d"
|
|
||||||
echo r
|
|
||||||
echo n
|
|
||||||
echo p
|
|
||||||
echo 1
|
|
||||||
echo 2048
|
|
||||||
echo 526335
|
|
||||||
echo t
|
|
||||||
echo c
|
|
||||||
echo n
|
|
||||||
echo p
|
|
||||||
echo 2
|
|
||||||
echo 526336
|
|
||||||
echo $ROOT_PART_END
|
|
||||||
echo a
|
|
||||||
echo 1
|
|
||||||
echo w
|
|
||||||
) | fdisk $TARGET_NAME
|
|
||||||
OUTPUT_DEVICE=$(sudo losetup --show -fP $TARGET_NAME)
|
|
||||||
sudo mkfs.ext4 `partition_for ${OUTPUT_DEVICE} 2`
|
|
||||||
sudo mkfs.vfat `partition_for ${OUTPUT_DEVICE} 1`
|
|
||||||
|
|
||||||
TMPDIR=$(mktemp -d)
|
|
||||||
|
|
||||||
sudo mount `partition_for ${OUTPUT_DEVICE} 2` $TMPDIR
|
|
||||||
sudo mkdir $TMPDIR/boot
|
|
||||||
sudo mount `partition_for ${OUTPUT_DEVICE} 1` $TMPDIR/boot
|
|
||||||
sudo unsquashfs -f -d $TMPDIR startos.raspberrypi.squashfs
|
|
||||||
REAL_GIT_HASH=$(cat $TMPDIR/usr/lib/startos/GIT_HASH.txt)
|
|
||||||
REAL_VERSION=$(cat $TMPDIR/usr/lib/startos/VERSION.txt)
|
|
||||||
REAL_ENVIRONMENT=$(cat $TMPDIR/usr/lib/startos/ENVIRONMENT.txt)
|
|
||||||
sudo sed -i 's| boot=startos| init=/usr/lib/startos/scripts/init_resize\.sh|' $TMPDIR/boot/cmdline.txt
|
|
||||||
sudo cp ./build/raspberrypi/fstab $TMPDIR/etc/
|
|
||||||
sudo cp ./build/raspberrypi/init_resize.sh $TMPDIR/usr/lib/startos/scripts/init_resize.sh
|
|
||||||
sudo umount $TMPDIR/boot
|
|
||||||
sudo umount $TMPDIR
|
|
||||||
sudo losetup -d $OUTPUT_DEVICE
|
|
||||||
|
|
||||||
if [ "$ALLOW_VERSION_MISMATCH" != 1 ]; then
|
|
||||||
if [ "$(cat GIT_HASH.txt)" != "$REAL_GIT_HASH" ]; then
|
|
||||||
>&2 echo "startos.raspberrypi.squashfs GIT_HASH.txt mismatch"
|
|
||||||
>&2 echo "expected $REAL_GIT_HASH (dpkg) found $(cat GIT_HASH.txt) (repo)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ "$(cat VERSION.txt)" != "$REAL_VERSION" ]; then
|
|
||||||
>&2 echo "startos.raspberrypi.squashfs VERSION.txt mismatch"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ "$(cat ENVIRONMENT.txt)" != "$REAL_ENVIRONMENT" ]; then
|
|
||||||
>&2 echo "startos.raspberrypi.squashfs ENVIRONMENT.txt mismatch"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
142
build/upload-ota.sh
Executable file
142
build/upload-ota.sh
Executable file
@@ -0,0 +1,142 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
>&2 echo '$VERSION required'
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$SKIP_DL" != "1" ]; then
|
||||||
|
if [ "$SKIP_CLEAN" != "1" ]; then
|
||||||
|
rm -rf ~/Downloads/v$VERSION
|
||||||
|
mkdir ~/Downloads/v$VERSION
|
||||||
|
cd ~/Downloads/v$VERSION
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$RUN_ID" ]; then
|
||||||
|
for arch in aarch64 aarch64-nonfree riscv64 x86_64 x86_64-nonfree; do
|
||||||
|
while ! gh run download -R Start9Labs/start-os $RUN_ID -n $arch.squashfs -D $(pwd); do sleep 1; done
|
||||||
|
done
|
||||||
|
for arch in aarch64 aarch64-nonfree riscv64 x86_64 x86_64-nonfree; do
|
||||||
|
while ! gh run download -R Start9Labs/start-os $RUN_ID -n $arch.iso -D $(pwd); do sleep 1; done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$ST_RUN_ID" ]; then
|
||||||
|
for arch in aarch64 riscv64 x86_64; do
|
||||||
|
while ! gh run download -R Start9Labs/start-os $ST_RUN_ID -n start-tunnel_$arch.deb -D $(pwd); do sleep 1; done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$CLI_RUN_ID" ]; then
|
||||||
|
for arch in aarch64 riscv64 x86_64; do
|
||||||
|
for os in linux macos; do
|
||||||
|
pair=${arch}-${os}
|
||||||
|
if [ "${pair}" = "riscv64-linux" ]; then
|
||||||
|
target=riscv64gc-unknown-linux-musl
|
||||||
|
elif [ "${pair}" = "riscv64-macos" ]; then
|
||||||
|
continue
|
||||||
|
elif [ "${os}" = "linux" ]; then
|
||||||
|
target="${arch}-unknown-linux-musl"
|
||||||
|
elif [ "${os}" = "macos" ]; then
|
||||||
|
target="${arch}-apple-darwin"
|
||||||
|
fi
|
||||||
|
while ! gh run download -R Start9Labs/start-os $CLI_RUN_ID -n start-cli_$target -D $(pwd); do sleep 1; done
|
||||||
|
mv start-cli "start-cli_${pair}"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cd ~/Downloads/v$VERSION
|
||||||
|
fi
|
||||||
|
|
||||||
|
start-cli --registry=https://alpha-registry-x.start9.com registry os version add $VERSION "v$VERSION" '' ">=0.3.5 <=$VERSION"
|
||||||
|
|
||||||
|
if [ "$SKIP_UL" = "2" ]; then
|
||||||
|
exit 2
|
||||||
|
elif [ "$SKIP_UL" != "1" ]; then
|
||||||
|
for file in *.deb start-cli_*; do
|
||||||
|
gh release upload -R Start9Labs/start-os v$VERSION $file
|
||||||
|
done
|
||||||
|
for file in *.iso *.squashfs; do
|
||||||
|
s3cmd put -P $file s3://startos-images/v$VERSION/$file
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$SKIP_INDEX" != "1" ]; then
|
||||||
|
for arch in aarch64 aarch64-nonfree riscv64 x86_64 x86_64-nonfree; do
|
||||||
|
for file in *_$arch.squashfs *_$arch.iso; do
|
||||||
|
start-cli --registry=https://alpha-registry-x.start9.com registry os asset add --platform=$arch --version=$VERSION $file https://startos-images.nyc3.cdn.digitaloceanspaces.com/v$VERSION/$file
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
for file in *.iso *.squashfs *.deb start-cli_*; do
|
||||||
|
gpg -u 7CFFDA41CA66056A --detach-sign --armor -o "${file}.asc" "$file"
|
||||||
|
done
|
||||||
|
|
||||||
|
gpg --export -a 7CFFDA41CA66056A > dr-bonez.key.asc
|
||||||
|
tar -czvf signatures.tar.gz *.asc
|
||||||
|
|
||||||
|
gh release upload -R Start9Labs/start-os v$VERSION signatures.tar.gz
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
# ISO Downloads
|
||||||
|
|
||||||
|
- [x86_64/AMD64](https://startos-images.nyc3.cdn.digitaloceanspaces.com/v$VERSION/$(ls *_x86_64-nonfree.iso))
|
||||||
|
- [x86_64/AMD64-slim (FOSS-only)](https://startos-images.nyc3.cdn.digitaloceanspaces.com/v$VERSION/$(ls *_x86_64.iso) "Without proprietary software or drivers")
|
||||||
|
- [aarch64/ARM64](https://startos-images.nyc3.cdn.digitaloceanspaces.com/v$VERSION/$(ls *_aarch64-nonfree.iso))
|
||||||
|
- [aarch64/ARM64-slim (FOSS-Only)](https://startos-images.nyc3.cdn.digitaloceanspaces.com/v$VERSION/$(ls *_aarch64.iso) "Without proprietary software or drivers")
|
||||||
|
- [RISCV64 (RVA23)](https://startos-images.nyc3.cdn.digitaloceanspaces.com/v$VERSION/$(ls *_riscv64.iso))
|
||||||
|
|
||||||
|
EOF
|
||||||
|
cat << 'EOF'
|
||||||
|
# StartOS Checksums
|
||||||
|
|
||||||
|
## SHA-256
|
||||||
|
```
|
||||||
|
EOF
|
||||||
|
sha256sum *.iso *.squashfs
|
||||||
|
cat << 'EOF'
|
||||||
|
```
|
||||||
|
|
||||||
|
## BLAKE-3
|
||||||
|
```
|
||||||
|
EOF
|
||||||
|
b3sum *.iso *.squashfs
|
||||||
|
cat << 'EOF'
|
||||||
|
```
|
||||||
|
|
||||||
|
# Start-Tunnel Checksums
|
||||||
|
|
||||||
|
## SHA-256
|
||||||
|
```
|
||||||
|
EOF
|
||||||
|
sha256sum start-tunnel*.deb
|
||||||
|
cat << 'EOF'
|
||||||
|
```
|
||||||
|
|
||||||
|
## BLAKE-3
|
||||||
|
```
|
||||||
|
EOF
|
||||||
|
b3sum start-tunnel*.deb
|
||||||
|
cat << 'EOF'
|
||||||
|
```
|
||||||
|
|
||||||
|
# start-cli Checksums
|
||||||
|
|
||||||
|
## SHA-256
|
||||||
|
```
|
||||||
|
EOF
|
||||||
|
sha256sum start-cli_*
|
||||||
|
cat << 'EOF'
|
||||||
|
```
|
||||||
|
|
||||||
|
## BLAKE-3
|
||||||
|
```
|
||||||
|
EOF
|
||||||
|
b3sum start-cli_*
|
||||||
|
cat << 'EOF'
|
||||||
|
```
|
||||||
|
EOF
|
||||||
@@ -4,6 +4,7 @@ OnFailure=container-runtime-failure.service
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
|
Environment=RUST_LOG=startos=debug
|
||||||
ExecStart=/usr/bin/node --experimental-detect-module --trace-warnings --unhandled-rejections=warn /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
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
mkdir -p /run/systemd/resolve
|
|
||||||
echo "nameserver 8.8.8.8" > /run/systemd/resolve/stub-resolv.conf
|
|
||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y curl rsync qemu-user-static nodejs
|
apt-get install -y curl rsync qemu-user-static nodejs
|
||||||
|
|
||||||
@@ -16,7 +13,4 @@ sed -i '/\(^\|#\)ForwardToSyslog=/c\ForwardToSyslog=no' /etc/systemd/journald.co
|
|||||||
|
|
||||||
systemctl enable container-runtime.service
|
systemctl enable container-runtime.service
|
||||||
|
|
||||||
rm -rf /run/systemd
|
|
||||||
|
|
||||||
rm -f /etc/resolv.conf
|
|
||||||
echo "nameserver 10.0.3.1" > /etc/resolv.conf
|
echo "nameserver 10.0.3.1" > /etc/resolv.conf
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
IMAGE=$1
|
|
||||||
|
|
||||||
if [ -z "$IMAGE" ]; then
|
|
||||||
>&2 echo "usage: $0 <image id>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [ -d "/media/images/$IMAGE" ]; then
|
|
||||||
>&2 echo "image does not exist"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
container=$(mktemp -d)
|
|
||||||
mkdir -p $container/rootfs $container/upper $container/work
|
|
||||||
mount -t overlay -olowerdir=/media/images/$IMAGE,upperdir=$container/upper,workdir=$container/work overlay $container/rootfs
|
|
||||||
|
|
||||||
rootfs=$container/rootfs
|
|
||||||
|
|
||||||
for special in dev sys proc run; do
|
|
||||||
mkdir -p $rootfs/$special
|
|
||||||
mount --bind /$special $rootfs/$special
|
|
||||||
done
|
|
||||||
|
|
||||||
echo $rootfs
|
|
||||||
2
container-runtime/package-lock.json
generated
2
container-runtime/package-lock.json
generated
@@ -38,7 +38,7 @@
|
|||||||
},
|
},
|
||||||
"../sdk/dist": {
|
"../sdk/dist": {
|
||||||
"name": "@start9labs/start-sdk",
|
"name": "@start9labs/start-sdk",
|
||||||
"version": "0.4.0-beta.43",
|
"version": "0.4.0-beta.48",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^3.0.0",
|
"@iarna/toml": "^3.0.0",
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
rootfs=$1
|
|
||||||
if [ -z "$rootfs" ]; then
|
|
||||||
>&2 echo "usage: $0 <container rootfs path>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
umount --recursive $rootfs
|
|
||||||
rm -rf $rootfs/..
|
|
||||||
@@ -178,6 +178,13 @@ export function makeEffects(context: EffectContext): Effects {
|
|||||||
T.Effects["getInstalledPackages"]
|
T.Effects["getInstalledPackages"]
|
||||||
>
|
>
|
||||||
},
|
},
|
||||||
|
getServiceManifest(
|
||||||
|
...[options]: Parameters<T.Effects["getServiceManifest"]>
|
||||||
|
) {
|
||||||
|
return rpcRound("get-service-manifest", options) as ReturnType<
|
||||||
|
T.Effects["getServiceManifest"]
|
||||||
|
>
|
||||||
|
},
|
||||||
subcontainer: {
|
subcontainer: {
|
||||||
createFs(options: { imageId: string; name: string }) {
|
createFs(options: { imageId: string; name: string }) {
|
||||||
return rpcRound("subcontainer.create-fs", options) as ReturnType<
|
return rpcRound("subcontainer.create-fs", options) as ReturnType<
|
||||||
@@ -289,6 +296,7 @@ export function makeEffects(context: EffectContext): Effects {
|
|||||||
getStatus(...[o]: Parameters<T.Effects["getStatus"]>) {
|
getStatus(...[o]: Parameters<T.Effects["getStatus"]>) {
|
||||||
return rpcRound("get-status", o) as ReturnType<T.Effects["getStatus"]>
|
return rpcRound("get-status", o) as ReturnType<T.Effects["getStatus"]>
|
||||||
},
|
},
|
||||||
|
/// DEPRECATED
|
||||||
setMainStatus(o: { status: "running" | "stopped" }): Promise<null> {
|
setMainStatus(o: { status: "running" | "stopped" }): Promise<null> {
|
||||||
return rpcRound("set-main-status", o) as ReturnType<
|
return rpcRound("set-main-status", o) as ReturnType<
|
||||||
T.Effects["setHealth"]
|
T.Effects["setHealth"]
|
||||||
@@ -311,6 +319,7 @@ export function makeEffects(context: EffectContext): Effects {
|
|||||||
}
|
}
|
||||||
if (context.callbacks?.onLeaveContext)
|
if (context.callbacks?.onLeaveContext)
|
||||||
self.onLeaveContext(() => {
|
self.onLeaveContext(() => {
|
||||||
|
self.constRetry = undefined
|
||||||
self.isInContext = false
|
self.isInContext = false
|
||||||
self.onLeaveContext = () => {
|
self.onLeaveContext = () => {
|
||||||
console.warn(
|
console.warn(
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ const handleRpc = (id: IdType, result: Promise<RpcResult>) =>
|
|||||||
|
|
||||||
const hasId = object({ id: idType }).test
|
const hasId = object({ id: idType }).test
|
||||||
export class RpcListener {
|
export class RpcListener {
|
||||||
|
shouldExit = false
|
||||||
unixSocketServer = net.createServer(async (server) => {})
|
unixSocketServer = net.createServer(async (server) => {})
|
||||||
private _system: System | undefined
|
private _system: System | undefined
|
||||||
private callbacks: CallbackHolder | undefined
|
private callbacks: CallbackHolder | undefined
|
||||||
@@ -158,6 +159,8 @@ export class RpcListener {
|
|||||||
|
|
||||||
this.unixSocketServer.listen(SOCKET_PATH)
|
this.unixSocketServer.listen(SOCKET_PATH)
|
||||||
|
|
||||||
|
console.log("Listening on %s", SOCKET_PATH)
|
||||||
|
|
||||||
this.unixSocketServer.on("connection", (s) => {
|
this.unixSocketServer.on("connection", (s) => {
|
||||||
let id: IdType = null
|
let id: IdType = null
|
||||||
const captureId = <X>(x: X) => {
|
const captureId = <X>(x: X) => {
|
||||||
@@ -208,6 +211,11 @@ export class RpcListener {
|
|||||||
.catch(mapError)
|
.catch(mapError)
|
||||||
.then(logData("response"))
|
.then(logData("response"))
|
||||||
.then(writeDataToSocket)
|
.then(writeDataToSocket)
|
||||||
|
.then((_) => {
|
||||||
|
if (this.shouldExit) {
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error(`Major error in socket handling: ${e}`)
|
console.error(`Major error in socket handling: ${e}`)
|
||||||
console.debug(`Data in: ${a.toString()}`)
|
console.debug(`Data in: ${a.toString()}`)
|
||||||
@@ -284,10 +292,13 @@ export class RpcListener {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.when(stopType, async ({ id }) => {
|
.when(stopType, async ({ id }) => {
|
||||||
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 }
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.when(exitType, async ({ id, params }) => {
|
.when(exitType, async ({ id, params }) => {
|
||||||
@@ -308,6 +319,7 @@ export class RpcListener {
|
|||||||
}),
|
}),
|
||||||
target,
|
target,
|
||||||
)
|
)
|
||||||
|
this.shouldExit = true
|
||||||
}
|
}
|
||||||
})().then((result) => ({ result })),
|
})().then((result) => ({ result })),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export class DockerProcedureContainer extends Drop {
|
|||||||
subpath: volumeMount.path,
|
subpath: volumeMount.path,
|
||||||
readonly: volumeMount.readonly,
|
readonly: volumeMount.readonly,
|
||||||
volumeId: volumeMount["volume-id"],
|
volumeId: volumeMount["volume-id"],
|
||||||
filetype: "directory",
|
idmap: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else if (volumeMount.type === "backup") {
|
} else if (volumeMount.type === "backup") {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { SDKManifest } from "@start9labs/start-sdk/base/lib/types"
|
|||||||
import { SubContainerRc } from "@start9labs/start-sdk/package/lib/util/SubContainer"
|
import { SubContainerRc } from "@start9labs/start-sdk/package/lib/util/SubContainer"
|
||||||
|
|
||||||
const EMBASSY_HEALTH_INTERVAL = 15 * 1000
|
const EMBASSY_HEALTH_INTERVAL = 15 * 1000
|
||||||
const EMBASSY_PROPERTIES_LOOP = 30 * 1000
|
|
||||||
/**
|
/**
|
||||||
* We wanted something to represent what the main loop is doing, and
|
* We wanted something to represent what the main loop is doing, and
|
||||||
* in this case it used to run the properties, health, and the docker/ js main.
|
* in this case it used to run the properties, health, and the docker/ js main.
|
||||||
@@ -120,6 +119,7 @@ export class MainLoop {
|
|||||||
? {
|
? {
|
||||||
preferredExternalPort: lanConf.external,
|
preferredExternalPort: lanConf.external,
|
||||||
alpn: { specified: ["http/1.1"] },
|
alpn: { specified: ["http/1.1"] },
|
||||||
|
addXForwardedHeaders: false,
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
})
|
})
|
||||||
@@ -133,7 +133,7 @@ export class MainLoop {
|
|||||||
delete this.mainEvent
|
delete this.mainEvent
|
||||||
delete this.healthLoops
|
delete this.healthLoops
|
||||||
await main?.daemon
|
await main?.daemon
|
||||||
.stop()
|
.term()
|
||||||
.catch((e: unknown) => console.error(`Main loop error`, utils.asError(e)))
|
.catch((e: unknown) => console.error(`Main loop error`, utils.asError(e)))
|
||||||
this.effects.setMainStatus({ status: "stopped" })
|
this.effects.setMainStatus({ status: "stopped" })
|
||||||
if (healthLoops) healthLoops.forEach((x) => clearInterval(x.interval))
|
if (healthLoops) healthLoops.forEach((x) => clearInterval(x.interval))
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import {
|
|||||||
transformOldConfigToNew,
|
transformOldConfigToNew,
|
||||||
} from "./transformConfigSpec"
|
} from "./transformConfigSpec"
|
||||||
import { partialDiff } from "@start9labs/start-sdk/base/lib/util"
|
import { partialDiff } from "@start9labs/start-sdk/base/lib/util"
|
||||||
|
import { Volume } from "@start9labs/start-sdk/package/lib/util/Volume"
|
||||||
|
|
||||||
type Optional<A> = A | undefined | null
|
type Optional<A> = A | undefined | null
|
||||||
function todo(): never {
|
function todo(): never {
|
||||||
@@ -61,14 +62,14 @@ export const EMBASSY_JS_LOCATION = "/usr/lib/startos/package/embassy.js"
|
|||||||
|
|
||||||
const configFile = FileHelper.json(
|
const configFile = FileHelper.json(
|
||||||
{
|
{
|
||||||
volumeId: "embassy",
|
base: new Volume("embassy"),
|
||||||
subpath: "config.json",
|
subpath: "config.json",
|
||||||
},
|
},
|
||||||
matches.any,
|
matches.any,
|
||||||
)
|
)
|
||||||
const dependsOnFile = FileHelper.json(
|
const dependsOnFile = FileHelper.json(
|
||||||
{
|
{
|
||||||
volumeId: "embassy",
|
base: new Volume("embassy"),
|
||||||
subpath: "dependsOn.json",
|
subpath: "dependsOn.json",
|
||||||
},
|
},
|
||||||
dictionary([string, array(string)]),
|
dictionary([string, array(string)]),
|
||||||
@@ -287,7 +288,6 @@ function convertProperties(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_REGISTRY = "https://registry.start9.com"
|
|
||||||
export class SystemForEmbassy implements System {
|
export class SystemForEmbassy implements System {
|
||||||
private version: ExtendedVersion
|
private version: ExtendedVersion
|
||||||
currentRunning: MainLoop | undefined
|
currentRunning: MainLoop | undefined
|
||||||
@@ -331,6 +331,10 @@ export class SystemForEmbassy implements System {
|
|||||||
) {
|
) {
|
||||||
this.version.upstream.prerelease = ["alpha"]
|
this.version.upstream.prerelease = ["alpha"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.manifest.id === "nostr") {
|
||||||
|
this.manifest.id = "nostr-rs-relay"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(
|
async init(
|
||||||
@@ -456,6 +460,7 @@ export class SystemForEmbassy implements System {
|
|||||||
addSsl = {
|
addSsl = {
|
||||||
preferredExternalPort: lanPortNum,
|
preferredExternalPort: lanPortNum,
|
||||||
alpn: { specified: [] },
|
alpn: { specified: [] },
|
||||||
|
addXForwardedHeaders: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
@@ -888,7 +893,6 @@ export class SystemForEmbassy implements System {
|
|||||||
effects: Effects,
|
effects: Effects,
|
||||||
timeoutMs: number | null,
|
timeoutMs: number | null,
|
||||||
): Promise<PropertiesReturn> {
|
): Promise<PropertiesReturn> {
|
||||||
// TODO BLU-J set the properties ever so often
|
|
||||||
const setConfigValue = this.manifest.properties
|
const setConfigValue = this.manifest.properties
|
||||||
if (!setConfigValue) throw new Error("There is no properties")
|
if (!setConfigValue) throw new Error("There is no properties")
|
||||||
if (setConfigValue.type === "docker") {
|
if (setConfigValue.type === "docker") {
|
||||||
@@ -1043,7 +1047,7 @@ export class SystemForEmbassy implements System {
|
|||||||
volumeId: "embassy",
|
volumeId: "embassy",
|
||||||
subpath: null,
|
subpath: null,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
filetype: "directory",
|
idmap: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
configFile
|
configFile
|
||||||
@@ -1191,7 +1195,7 @@ async function updateConfig(
|
|||||||
volumeId: "embassy",
|
volumeId: "embassy",
|
||||||
subpath: null,
|
subpath: null,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
filetype: "directory",
|
idmap: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const remoteConfig = configFile
|
const remoteConfig = configFile
|
||||||
@@ -1241,11 +1245,11 @@ async function updateConfig(
|
|||||||
: catchFn(
|
: catchFn(
|
||||||
() =>
|
() =>
|
||||||
(specValue.target === "lan-address"
|
(specValue.target === "lan-address"
|
||||||
? filled.addressInfo!.localHostnames[0] ||
|
? filled.addressInfo!.filter({ kind: "mdns" }) ||
|
||||||
filled.addressInfo!.onionHostnames[0]
|
filled.addressInfo!.onion
|
||||||
: filled.addressInfo!.onionHostnames[0] ||
|
: filled.addressInfo!.onion ||
|
||||||
filled.addressInfo!.localHostnames[0]
|
filled.addressInfo!.filter({ kind: "mdns" })
|
||||||
).hostname.value,
|
).hostnames[0].hostname.value,
|
||||||
) || ""
|
) || ""
|
||||||
mutConfigValue[key] = url
|
mutConfigValue[key] = url
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,22 +68,18 @@ export class SystemForStartOs implements System {
|
|||||||
try {
|
try {
|
||||||
if (this.runningMain || this.starting) return
|
if (this.runningMain || this.starting) return
|
||||||
this.starting = true
|
this.starting = true
|
||||||
effects.constRetry = utils.once(() => effects.restart())
|
effects.constRetry = utils.once(() => {
|
||||||
|
console.debug(".const() triggered")
|
||||||
|
effects.restart()
|
||||||
|
})
|
||||||
let mainOnTerm: () => Promise<void> | undefined
|
let mainOnTerm: () => Promise<void> | undefined
|
||||||
const started = async (onTerm: () => Promise<void>) => {
|
|
||||||
await effects.setMainStatus({ status: "running" })
|
|
||||||
mainOnTerm = onTerm
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const daemons = await (
|
const daemons = await (
|
||||||
await this.abi.main({
|
await this.abi.main({
|
||||||
effects,
|
effects,
|
||||||
started,
|
|
||||||
})
|
})
|
||||||
).build()
|
).build()
|
||||||
this.runningMain = {
|
this.runningMain = {
|
||||||
stop: async () => {
|
stop: async () => {
|
||||||
if (mainOnTerm) await mainOnTerm()
|
|
||||||
await daemons.term()
|
await daemons.term()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ const getDependencies: AllGetDependencies = {
|
|||||||
system: getSystem,
|
system: getSystem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let s of ["SIGTERM", "SIGINT", "SIGHUP"]) {
|
||||||
|
process.on(s, (s) => {
|
||||||
|
console.log(`Caught ${s}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
new RpcListener(getDependencies)
|
new RpcListener(getDependencies)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
21
container-runtime/update-image-local.sh
Executable file
21
container-runtime/update-image-local.sh
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
||||||
|
|
||||||
|
USE_TTY=
|
||||||
|
if tty -s; then
|
||||||
|
USE_TTY="-it"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOCKER_PLATFORM=linux/${ARCH}
|
||||||
|
case $ARCH in
|
||||||
|
x86_64)
|
||||||
|
DOCKER_PLATFORM=linux/amd64;;
|
||||||
|
aarch64)
|
||||||
|
DOCKER_PLATFORM=linux/arm64;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
docker run --rm $USE_TTY --platform=$DOCKER_PLATFORM -eARCH --privileged -v "$(pwd):/root/start-os" start9/build-env /root/start-os/container-runtime/update-image.sh
|
||||||
|
if [ "$(ls -nd "rootfs.${ARCH}.squashfs" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
docker run --rm $USE_TTY -v "$(pwd):/root/start-os" start9/build-env chown -R $UID:$UID /root/start-os/container-runtime
|
||||||
|
fi
|
||||||
@@ -9,56 +9,34 @@ if [ "$ARCH" = "riscv64" ]; then
|
|||||||
RUST_ARCH="riscv64gc"
|
RUST_ARCH="riscv64gc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if mountpoint -q tmp/combined; then sudo umount -R tmp/combined; fi
|
mount -t tmpfs tmpfs /tmp
|
||||||
if mountpoint -q tmp/lower; then sudo umount tmp/lower; fi
|
mkdir -p /tmp/lower /tmp/upper /tmp/work /tmp/combined
|
||||||
sudo rm -rf tmp
|
mount -o loop debian.${ARCH}.squashfs /tmp/lower
|
||||||
mkdir -p tmp/lower tmp/upper tmp/work tmp/combined
|
mount -t overlay -olowerdir=/tmp/lower,upperdir=/tmp/upper,workdir=/tmp/work overlay /tmp/combined
|
||||||
if which squashfuse > /dev/null; then
|
|
||||||
sudo squashfuse debian.${ARCH}.squashfs tmp/lower
|
|
||||||
else
|
|
||||||
sudo mount debian.${ARCH}.squashfs tmp/lower
|
|
||||||
fi
|
|
||||||
if which fuse-overlayfs > /dev/null; then
|
|
||||||
sudo fuse-overlayfs -olowerdir=tmp/lower,upperdir=tmp/upper,workdir=tmp/work overlay tmp/combined
|
|
||||||
else
|
|
||||||
sudo mount -t overlay -olowerdir=tmp/lower,upperdir=tmp/upper,workdir=tmp/work overlay tmp/combined
|
|
||||||
fi
|
|
||||||
|
|
||||||
QEMU=
|
mkdir -p /tmp/combined/usr/lib/startos/
|
||||||
if [ "$ARCH" != "$(uname -m)" ]; then
|
rsync -a --copy-unsafe-links --info=progress2 dist/ /tmp/combined/usr/lib/startos/init/
|
||||||
QEMU=/usr/bin/qemu-${ARCH}-static
|
chown -R 0:0 /tmp/combined/usr/lib/startos/
|
||||||
if ! which qemu-$ARCH-static > /dev/null; then
|
cp container-runtime.service /tmp/combined/lib/systemd/system/container-runtime.service
|
||||||
>&2 echo qemu-user-static is required for cross-platform builds
|
chown 0:0 /tmp/combined/lib/systemd/system/container-runtime.service
|
||||||
sudo umount tmp/combined
|
cp container-runtime-failure.service /tmp/combined/lib/systemd/system/container-runtime-failure.service
|
||||||
sudo umount tmp/lower
|
chown 0:0 /tmp/combined/lib/systemd/system/container-runtime-failure.service
|
||||||
sudo rm -rf tmp
|
cp ../core/target/${RUST_ARCH}-unknown-linux-musl/release/start-container /tmp/combined/usr/bin/start-container
|
||||||
exit 1
|
echo -e '#!/bin/bash\nexec start-container "$@"' > /tmp/combined/usr/bin/start-cli # TODO: remove
|
||||||
fi
|
chmod +x /tmp/combined/usr/bin/start-cli
|
||||||
sudo cp $(which qemu-$ARCH-static) tmp/combined${QEMU}
|
chown 0:0 /tmp/combined/usr/bin/start-container
|
||||||
fi
|
echo container-runtime | sha256sum | head -c 32 | cat - <(echo) > /tmp/combined/etc/machine-id
|
||||||
|
rm -f /tmp/combined/etc/resolv.conf
|
||||||
sudo mkdir -p tmp/combined/usr/lib/startos/
|
cp /etc/resolv.conf /tmp/combined/etc/resolv.conf
|
||||||
sudo rsync -a --copy-unsafe-links dist/ tmp/combined/usr/lib/startos/init/
|
for fs in proc sys dev; do
|
||||||
sudo chown -R 0:0 tmp/combined/usr/lib/startos/
|
mount --bind /$fs /tmp/combined/$fs
|
||||||
sudo cp container-runtime.service tmp/combined/lib/systemd/system/container-runtime.service
|
done
|
||||||
sudo chown 0:0 tmp/combined/lib/systemd/system/container-runtime.service
|
cat deb-install.sh | chroot /tmp/combined /bin/bash
|
||||||
sudo cp container-runtime-failure.service tmp/combined/lib/systemd/system/container-runtime-failure.service
|
for fs in proc sys dev; do
|
||||||
sudo chown 0:0 tmp/combined/lib/systemd/system/container-runtime-failure.service
|
umount /tmp/combined/$fs
|
||||||
sudo cp ../core/target/${RUST_ARCH}-unknown-linux-musl/release/containerbox tmp/combined/usr/bin/start-container
|
done
|
||||||
echo -e '#!/bin/bash\nexec start-container "$@"' | sudo tee tmp/combined/usr/bin/start-cli # TODO: remove
|
truncate -s 0 /tmp/combined/etc/machine-id
|
||||||
sudo chmod +x tmp/combined/usr/bin/start-cli
|
|
||||||
sudo chown 0:0 tmp/combined/usr/bin/start-container
|
|
||||||
echo container-runtime | sha256sum | head -c 32 | cat - <(echo) | sudo tee tmp/combined/etc/machine-id
|
|
||||||
cat deb-install.sh | sudo systemd-nspawn --console=pipe -D tmp/combined $QEMU /bin/bash
|
|
||||||
sudo truncate -s 0 tmp/combined/etc/machine-id
|
|
||||||
|
|
||||||
if [ -n "$QEMU" ]; then
|
|
||||||
sudo rm tmp/combined${QEMU}
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f rootfs.${ARCH}.squashfs
|
rm -f rootfs.${ARCH}.squashfs
|
||||||
mkdir -p ../build/lib/container-runtime
|
mkdir -p ../build/lib/container-runtime
|
||||||
sudo mksquashfs tmp/combined rootfs.${ARCH}.squashfs
|
mksquashfs /tmp/combined rootfs.${ARCH}.squashfs
|
||||||
sudo umount tmp/combined
|
|
||||||
sudo umount tmp/lower
|
|
||||||
sudo rm -rf tmp
|
|
||||||
2
core/.gitignore
vendored
2
core/.gitignore
vendored
@@ -8,4 +8,4 @@ secrets.db
|
|||||||
.env
|
.env
|
||||||
.editorconfig
|
.editorconfig
|
||||||
proptest-regressions/**/*
|
proptest-regressions/**/*
|
||||||
/startos/bindings/*
|
/bindings/*
|
||||||
1672
core/Cargo.lock
generated
1672
core/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
293
core/Cargo.toml
293
core/Cargo.toml
@@ -1,3 +1,292 @@
|
|||||||
[workspace]
|
[package]
|
||||||
|
authors = ["Aiden McClelland <me@drbonez.dev>"]
|
||||||
|
description = "The core of StartOS"
|
||||||
|
documentation = "https://docs.rs/start-os"
|
||||||
|
edition = "2024"
|
||||||
|
keywords = [
|
||||||
|
"bitcoin",
|
||||||
|
"full-node",
|
||||||
|
"lightning",
|
||||||
|
"privacy",
|
||||||
|
"raspberry-pi",
|
||||||
|
"self-hosted",
|
||||||
|
]
|
||||||
|
license = "MIT"
|
||||||
|
name = "start-os"
|
||||||
|
readme = "README.md"
|
||||||
|
repository = "https://github.com/Start9Labs/start-os"
|
||||||
|
version = "0.4.0-alpha.19" # VERSION_BUMP
|
||||||
|
|
||||||
members = ["helpers", "models", "startos"]
|
[lib]
|
||||||
|
name = "startos"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "startbox"
|
||||||
|
path = "src/main/startbox.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "start-cli"
|
||||||
|
path = "src/main/start-cli.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "start-container"
|
||||||
|
path = "src/main/start-container.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "registrybox"
|
||||||
|
path = "src/main/registrybox.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "tunnelbox"
|
||||||
|
path = "src/main/tunnelbox.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
arti = [
|
||||||
|
"arti-client",
|
||||||
|
"safelog",
|
||||||
|
"tor-cell",
|
||||||
|
"tor-hscrypto",
|
||||||
|
"tor-hsservice",
|
||||||
|
"tor-keymgr",
|
||||||
|
"tor-llcrypto",
|
||||||
|
"tor-proto",
|
||||||
|
"tor-rtcompat",
|
||||||
|
]
|
||||||
|
beta = []
|
||||||
|
console = ["console-subscriber", "tokio/tracing"]
|
||||||
|
default = []
|
||||||
|
dev = []
|
||||||
|
test = []
|
||||||
|
unstable = ["backtrace-on-stack-overflow"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
aes = { version = "0.7.5", features = ["ctr"] }
|
||||||
|
arti-client = { version = "0.33", features = [
|
||||||
|
"compression",
|
||||||
|
"ephemeral-keystore",
|
||||||
|
"experimental-api",
|
||||||
|
"onion-service-client",
|
||||||
|
"onion-service-service",
|
||||||
|
"rustls",
|
||||||
|
"static",
|
||||||
|
"tokio",
|
||||||
|
], default-features = false, git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
async-acme = { version = "0.6.0", git = "https://github.com/dr-bonez/async-acme.git", features = [
|
||||||
|
"use_rustls",
|
||||||
|
"use_tokio",
|
||||||
|
] }
|
||||||
|
async-compression = { version = "0.4.32", features = [
|
||||||
|
"brotli",
|
||||||
|
"gzip",
|
||||||
|
"tokio",
|
||||||
|
"zstd",
|
||||||
|
] }
|
||||||
|
async-stream = "0.3.5"
|
||||||
|
async-trait = "0.1.74"
|
||||||
|
axum = { version = "0.8.4", features = ["ws", "http2"] }
|
||||||
|
backtrace-on-stack-overflow = { version = "0.3.0", optional = true }
|
||||||
|
base32 = "0.5.0"
|
||||||
|
base64 = "0.22.1"
|
||||||
|
base64ct = "1.6.0"
|
||||||
|
basic-cookies = "0.1.4"
|
||||||
|
blake3 = { version = "1.5.0", features = ["mmap", "rayon"] }
|
||||||
|
bytes = "1"
|
||||||
|
chrono = { version = "0.4.31", features = ["serde"] }
|
||||||
|
clap = { version = "4.4.12", features = ["string"] }
|
||||||
|
color-eyre = "0.6.2"
|
||||||
|
console = "0.16.2"
|
||||||
|
console-subscriber = { version = "0.5.0", optional = true }
|
||||||
|
const_format = "0.2.34"
|
||||||
|
cookie = "0.18.0"
|
||||||
|
cookie_store = "0.22.0"
|
||||||
|
curve25519-dalek = "4.1.3"
|
||||||
|
der = { version = "0.7.9", features = ["derive", "pem"] }
|
||||||
|
digest = "0.10.7"
|
||||||
|
divrem = "1.0.0"
|
||||||
|
dns-lookup = "3.0.1"
|
||||||
|
ed25519 = { version = "2.2.3", features = ["alloc", "pem", "pkcs8"] }
|
||||||
|
ed25519-dalek = { version = "2.2.0", features = [
|
||||||
|
"digest",
|
||||||
|
"hazmat",
|
||||||
|
"pkcs8",
|
||||||
|
"rand_core",
|
||||||
|
"serde",
|
||||||
|
"zeroize",
|
||||||
|
] }
|
||||||
|
ed25519-dalek-v1 = { package = "ed25519-dalek", version = "1" }
|
||||||
|
exver = { version = "0.2.0", git = "https://github.com/Start9Labs/exver-rs.git", features = [
|
||||||
|
"serde",
|
||||||
|
] }
|
||||||
|
fd-lock-rs = "0.1.4"
|
||||||
|
form_urlencoded = "1.2.1"
|
||||||
|
futures = "0.3.28"
|
||||||
|
gpt = "4.1.0"
|
||||||
|
hex = "0.4.3"
|
||||||
|
hickory-server = { version = "0.25.2", features = ["resolver"] }
|
||||||
|
hmac = "0.12.1"
|
||||||
|
http = "1.0.0"
|
||||||
|
http-body-util = "0.1"
|
||||||
|
hyper = { version = "1.5", features = ["http1", "http2", "server"] }
|
||||||
|
hyper-util = { version = "0.1.10", features = [
|
||||||
|
"http1",
|
||||||
|
"http2",
|
||||||
|
"server",
|
||||||
|
"server-auto",
|
||||||
|
"server-graceful",
|
||||||
|
"service",
|
||||||
|
"tokio",
|
||||||
|
] }
|
||||||
|
id-pool = { version = "0.2.2", default-features = false, features = [
|
||||||
|
"serde",
|
||||||
|
"u16",
|
||||||
|
] }
|
||||||
|
iddqd = "0.3.14"
|
||||||
|
imbl = { version = "6", features = ["serde", "small-chunks"] }
|
||||||
|
imbl-value = { version = "0.4.3", features = ["ts-rs"] }
|
||||||
|
include_dir = { version = "0.7.3", features = ["metadata"] }
|
||||||
|
indexmap = { version = "2.0.2", features = ["serde"] }
|
||||||
|
indicatif = { version = "0.18.3", features = ["tokio"] }
|
||||||
|
inotify = "0.11.0"
|
||||||
|
integer-encoding = { version = "4.0.0", features = ["tokio_async"] }
|
||||||
|
ipnet = { version = "2.8.0", features = ["serde"] }
|
||||||
|
isocountry = "0.3.2"
|
||||||
|
itertools = "0.14.0"
|
||||||
|
jaq-core = "0.10.1"
|
||||||
|
jaq-std = "0.10.0"
|
||||||
|
josekit = "0.10.3"
|
||||||
|
jsonpath_lib = { git = "https://github.com/Start9Labs/jsonpath.git" }
|
||||||
|
lazy_async_pool = "0.3.3"
|
||||||
|
lazy_format = "2.0"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
lettre = { version = "0.11.18", default-features = false, features = [
|
||||||
|
"aws-lc-rs",
|
||||||
|
"builder",
|
||||||
|
"hostname",
|
||||||
|
"pool",
|
||||||
|
"rustls-platform-verifier",
|
||||||
|
"smtp-transport",
|
||||||
|
"tokio1-rustls",
|
||||||
|
] }
|
||||||
|
libc = "0.2.149"
|
||||||
|
log = "0.4.20"
|
||||||
|
mbrman = "0.6.0"
|
||||||
|
miette = { version = "7.6.0", features = ["fancy"] }
|
||||||
|
mio = "1"
|
||||||
|
new_mime_guess = "4"
|
||||||
|
nix = { version = "0.30.1", features = [
|
||||||
|
"fs",
|
||||||
|
"hostname",
|
||||||
|
"mount",
|
||||||
|
"net",
|
||||||
|
"process",
|
||||||
|
"sched",
|
||||||
|
"signal",
|
||||||
|
"user",
|
||||||
|
] }
|
||||||
|
nom = "8.0.0"
|
||||||
|
num = "0.4.1"
|
||||||
|
num_cpus = "1.16.0"
|
||||||
|
num_enum = "0.7.0"
|
||||||
|
once_cell = "1.19.0"
|
||||||
|
openssh-keys = "0.6.2"
|
||||||
|
openssl = { version = "0.10.57", features = ["vendored"] }
|
||||||
|
p256 = { version = "0.13.2", features = ["pem"] }
|
||||||
|
patch-db = { version = "*", path = "../patch-db/patch-db", features = [
|
||||||
|
"trace",
|
||||||
|
] }
|
||||||
|
pbkdf2 = "0.12.2"
|
||||||
|
pin-project = "1.1.3"
|
||||||
|
pkcs8 = { version = "0.10.2", features = ["std"] }
|
||||||
|
prettytable-rs = "0.10.0"
|
||||||
|
proptest = "1.3.1"
|
||||||
|
proptest-derive = "0.7.0"
|
||||||
|
qrcode = "0.14.1"
|
||||||
|
r3bl_tui = "0.7.6"
|
||||||
|
rand = "0.9.2"
|
||||||
|
regex = "1.10.2"
|
||||||
|
reqwest = { version = "0.12.25", features = [
|
||||||
|
"json",
|
||||||
|
"socks",
|
||||||
|
"stream",
|
||||||
|
"http2",
|
||||||
|
] }
|
||||||
|
reqwest_cookie_store = "0.9.0"
|
||||||
|
rpassword = "7.2.0"
|
||||||
|
rust-argon2 = "3.0.0"
|
||||||
|
rust-i18n = "3.1.5"
|
||||||
|
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git" }
|
||||||
|
safelog = { version = "0.4.8", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
semver = { version = "1.0.20", features = ["serde"] }
|
||||||
|
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||||
|
serde_cbor = { package = "ciborium", version = "0.2.1" }
|
||||||
|
serde_json = "1.0"
|
||||||
|
serde_toml = { package = "toml", version = "0.9.9+spec-1.0.0" }
|
||||||
|
serde_yaml = { package = "serde_yml", version = "0.0.12" }
|
||||||
|
sha-crypt = "0.5.0"
|
||||||
|
sha2 = "0.10.2"
|
||||||
|
signal-hook = "0.3.17"
|
||||||
|
socket2 = { version = "0.6.0", features = ["all"] }
|
||||||
|
socks5-impl = { version = "0.7.2", features = ["client", "server"] }
|
||||||
|
sqlx = { version = "0.8.6", features = [
|
||||||
|
"postgres",
|
||||||
|
"runtime-tokio-rustls",
|
||||||
|
], default-features = false }
|
||||||
|
sscanf = "0.4.1"
|
||||||
|
ssh-key = { version = "0.6.2", features = ["ed25519"] }
|
||||||
|
tar = "0.4.40"
|
||||||
|
termion = "4.0.5"
|
||||||
|
textwrap = "0.16.1"
|
||||||
|
thiserror = "2.0.12"
|
||||||
|
tokio = { version = "1.38.1", features = ["full"] }
|
||||||
|
tokio-rustls = "0.26.4"
|
||||||
|
tokio-stream = { version = "0.1.14", features = ["io-util", "net", "sync"] }
|
||||||
|
tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" }
|
||||||
|
tokio-tungstenite = { version = "0.26.2", features = ["native-tls", "url"] }
|
||||||
|
tokio-util = { version = "0.7.9", features = ["io"] }
|
||||||
|
tor-cell = { version = "0.33", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
tor-hscrypto = { version = "0.33", features = [
|
||||||
|
"full",
|
||||||
|
], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
tor-hsservice = { version = "0.33", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
tor-keymgr = { version = "0.33", features = [
|
||||||
|
"ephemeral-keystore",
|
||||||
|
], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
tor-llcrypto = { version = "0.33", features = [
|
||||||
|
"full",
|
||||||
|
], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
tor-proto = { version = "0.33", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
tor-rtcompat = { version = "0.33", features = [
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
||||||
|
torut = "0.2.1"
|
||||||
|
tower-service = "0.3.3"
|
||||||
|
tracing = "0.1.39"
|
||||||
|
tracing-error = "0.2.0"
|
||||||
|
tracing-journald = "0.3.0"
|
||||||
|
tracing-subscriber = { version = "=0.3.19", features = ["env-filter"] }
|
||||||
|
ts-rs = "9.0.1"
|
||||||
|
typed-builder = "0.23.2"
|
||||||
|
url = { version = "2.4.1", features = ["serde"] }
|
||||||
|
uuid = { version = "1.4.1", features = ["v4"] }
|
||||||
|
visit-rs = "0.1.1"
|
||||||
|
x25519-dalek = { version = "2.0.1", features = ["static_secrets"] }
|
||||||
|
zbus = "5.1.1"
|
||||||
|
hashing-serializer = "0.1.1"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
|
procfs = "0.18.0"
|
||||||
|
pty-process = "0.5.1"
|
||||||
|
|
||||||
|
[profile.test]
|
||||||
|
opt-level = 3
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 3
|
||||||
|
|
||||||
|
[profile.dev.package.backtrace]
|
||||||
|
opt-level = 3
|
||||||
|
|
||||||
|
[profile.dev.package.sqlx-macros]
|
||||||
|
opt-level = 3
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
[build]
|
[build]
|
||||||
pre-build = ["apt-get update && apt-get install -y rsync"]
|
pre-build = ["apt-get update && apt-get install -y rsync"]
|
||||||
|
|
||||||
[build.env]
|
|
||||||
passthrough = ["RUST_BACKTRACE"]
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
|
||||||
|
|
||||||
set -ea
|
|
||||||
shopt -s expand_aliases
|
|
||||||
|
|
||||||
PROFILE=${PROFILE:-release}
|
|
||||||
if [ "${PROFILE}" = "release" ]; then
|
|
||||||
BUILD_FLAGS="--release"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${ARCH:-}" ]; then
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$ARCH" = "arm64" ]; then
|
|
||||||
ARCH="aarch64"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${KERNEL_NAME:-}" ]; then
|
|
||||||
KERNEL_NAME=$(uname -s)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${TARGET:-}" ]; then
|
|
||||||
if [ "$KERNEL_NAME" = "Linux" ]; then
|
|
||||||
TARGET="$ARCH-unknown-linux-musl"
|
|
||||||
elif [ "$KERNEL_NAME" = "Darwin" ]; then
|
|
||||||
TARGET="$ARCH-apple-darwin"
|
|
||||||
else
|
|
||||||
>&2 echo "unknown kernel $KERNEL_NAME"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# Ensure GIT_HASH.txt exists if not created by higher-level build steps
|
|
||||||
if [ ! -f GIT_HASH.txt ] && command -v git >/dev/null 2>&1; then
|
|
||||||
git rev-parse HEAD > GIT_HASH.txt || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
FEATURES="$(echo "${ENVIRONMENT:-}" | sed 's/-/,/g')"
|
|
||||||
FEATURE_ARGS="cli"
|
|
||||||
if [ -n "$FEATURES" ]; then
|
|
||||||
FEATURE_ARGS="$FEATURE_ARGS,$FEATURES"
|
|
||||||
fi
|
|
||||||
|
|
||||||
RUSTFLAGS=""
|
|
||||||
if [[ "${ENVIRONMENT:-}" =~ (^|-)console($|-) ]]; then
|
|
||||||
RUSTFLAGS="--cfg tokio_unstable"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "FEATURES=\"$FEATURES\""
|
|
||||||
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
|
||||||
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features $FEATURE_ARGS --locked --bin start-cli --target=$TARGET
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
|
||||||
|
|
||||||
set -ea
|
|
||||||
shopt -s expand_aliases
|
|
||||||
|
|
||||||
PROFILE=${PROFILE:-release}
|
|
||||||
if [ "${PROFILE}" = "release" ]; then
|
|
||||||
BUILD_FLAGS="--release"
|
|
||||||
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 ..
|
|
||||||
|
|
||||||
rm -rf core/startos/bindings/
|
|
||||||
|
|
||||||
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
|
||||||
RUSTFLAGS=""
|
|
||||||
if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
|
|
||||||
RUSTFLAGS="--cfg tokio_unstable"
|
|
||||||
fi
|
|
||||||
echo "FEATURES=\"$FEATURES\""
|
|
||||||
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
|
||||||
cross test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features test,$FEATURES --locked 'export_bindings_'
|
|
||||||
|
|
||||||
cd core/startos/bindings
|
|
||||||
|
|
||||||
for folder in $(find . -type d); do
|
|
||||||
(
|
|
||||||
cd $folder
|
|
||||||
find . -name '*.ts' -maxdepth 1 | sed 's/\.\/\([^.]*\)\.ts/export * from ".\/\1";/g' | grep -v '"./index"' | tee ./index.ts
|
|
||||||
find . -mindepth 1 -maxdepth 1 -type d | sed 's/\.\/\([^.]*\)/export * as \1 from ".\/\1";/g' | grep -v '"./index"' | tee -a ./index.ts
|
|
||||||
)
|
|
||||||
done
|
|
||||||
|
|
||||||
find . -name '*.ts' | xargs -P $(nproc) -I % npm --prefix ../../../sdk exec -- prettier --config ../../../sdk/base/package.json -w %
|
|
||||||
79
core/build/build-cli.sh
Executable file
79
core/build/build-cli.sh
Executable file
@@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
source ./builder-alias.sh
|
||||||
|
|
||||||
|
set -ea
|
||||||
|
|
||||||
|
INSTALL=false
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--install)
|
||||||
|
INSTALL=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
>&2 echo "Unknown option: $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
shopt -s expand_aliases
|
||||||
|
|
||||||
|
PROFILE=${PROFILE:-release}
|
||||||
|
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
|
||||||
|
|
||||||
|
if [ -z "${KERNEL_NAME:-}" ]; then
|
||||||
|
KERNEL_NAME=$(uname -s)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${TARGET:-}" ]; then
|
||||||
|
if [ "$KERNEL_NAME" = "Linux" ]; then
|
||||||
|
TARGET="$RUST_ARCH-unknown-linux-musl"
|
||||||
|
elif [ "$KERNEL_NAME" = "Darwin" ]; then
|
||||||
|
TARGET="$RUST_ARCH-apple-darwin"
|
||||||
|
else
|
||||||
|
>&2 echo "unknown kernel $KERNEL_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
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 zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin start-cli --target=$TARGET
|
||||||
|
if [ "$(ls -nd "core/target/$TARGET/$PROFILE/start-cli" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
rust-zig-builder sh -c "cd core && chown -R $UID:$UID target && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$INSTALL" = "true" ]; then
|
||||||
|
cp "core/target/$TARGET/$PROFILE/start-cli" ~/.cargo/bin/start-cli
|
||||||
|
fi
|
||||||
@@ -2,12 +2,19 @@
|
|||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
source ./builder-alias.sh
|
||||||
|
|
||||||
set -ea
|
set -ea
|
||||||
shopt -s expand_aliases
|
shopt -s expand_aliases
|
||||||
|
|
||||||
PROFILE=${PROFILE:-release}
|
PROFILE=${PROFILE:-release}
|
||||||
if [ "${PROFILE}" = "release" ]; then
|
if [ "${PROFILE}" = "release" ]; then
|
||||||
BUILD_FLAGS="--release"
|
BUILD_FLAGS="--release"
|
||||||
|
else
|
||||||
|
if [ "$PROFILE" != "debug"]; then
|
||||||
|
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
|
||||||
|
PROFILE=debug
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
if [ -z "$ARCH" ]; then
|
||||||
@@ -23,7 +30,7 @@ if [ "$ARCH" = "riscv64" ]; then
|
|||||||
RUST_ARCH="riscv64gc"
|
RUST_ARCH="riscv64gc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ..
|
cd ../..
|
||||||
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
||||||
RUSTFLAGS=""
|
RUSTFLAGS=""
|
||||||
|
|
||||||
@@ -33,4 +40,7 @@ fi
|
|||||||
|
|
||||||
echo "FEATURES=\"$FEATURES\""
|
echo "FEATURES=\"$FEATURES\""
|
||||||
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
||||||
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-registry,registry,$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
|
||||||
|
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/registrybox" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
fi
|
||||||
@@ -2,12 +2,19 @@
|
|||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
source ./builder-alias.sh
|
||||||
|
|
||||||
set -ea
|
set -ea
|
||||||
shopt -s expand_aliases
|
shopt -s expand_aliases
|
||||||
|
|
||||||
PROFILE=${PROFILE:-release}
|
PROFILE=${PROFILE:-release}
|
||||||
if [ "${PROFILE}" = "release" ]; then
|
if [ "${PROFILE}" = "release" ]; then
|
||||||
BUILD_FLAGS="--release"
|
BUILD_FLAGS="--release"
|
||||||
|
else
|
||||||
|
if [ "$PROFILE" != "debug"]; then
|
||||||
|
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
|
||||||
|
PROFILE=debug
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
if [ -z "$ARCH" ]; then
|
||||||
@@ -23,7 +30,7 @@ if [ "$ARCH" = "riscv64" ]; then
|
|||||||
RUST_ARCH="riscv64gc"
|
RUST_ARCH="riscv64gc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ..
|
cd ../..
|
||||||
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
||||||
RUSTFLAGS=""
|
RUSTFLAGS=""
|
||||||
|
|
||||||
@@ -33,4 +40,7 @@ fi
|
|||||||
|
|
||||||
echo "FEATURES=\"$FEATURES\""
|
echo "FEATURES=\"$FEATURES\""
|
||||||
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
||||||
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-container,$FEATURES --locked --bin containerbox --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
|
||||||
|
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/start-container" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
fi
|
||||||
@@ -2,12 +2,19 @@
|
|||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
source ./builder-alias.sh
|
||||||
|
|
||||||
set -ea
|
set -ea
|
||||||
shopt -s expand_aliases
|
shopt -s expand_aliases
|
||||||
|
|
||||||
PROFILE=${PROFILE:-release}
|
PROFILE=${PROFILE:-release}
|
||||||
if [ "${PROFILE}" = "release" ]; then
|
if [ "${PROFILE}" = "release" ]; then
|
||||||
BUILD_FLAGS="--release"
|
BUILD_FLAGS="--release"
|
||||||
|
else
|
||||||
|
if [ "$PROFILE" != "debug"]; then
|
||||||
|
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
|
||||||
|
PROFILE=debug
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
if [ -z "$ARCH" ]; then
|
||||||
@@ -23,7 +30,7 @@ if [ "$ARCH" = "riscv64" ]; then
|
|||||||
RUST_ARCH="riscv64gc"
|
RUST_ARCH="riscv64gc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ..
|
cd ../..
|
||||||
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
||||||
RUSTFLAGS=""
|
RUSTFLAGS=""
|
||||||
|
|
||||||
@@ -33,4 +40,7 @@ fi
|
|||||||
|
|
||||||
echo "FEATURES=\"$FEATURES\""
|
echo "FEATURES=\"$FEATURES\""
|
||||||
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
||||||
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli,startd,$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
|
||||||
|
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/startbox" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
fi
|
||||||
44
core/build/build-ts.sh
Executable file
44
core/build/build-ts.sh
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
source ./builder-alias.sh
|
||||||
|
|
||||||
|
set -ea
|
||||||
|
shopt -s expand_aliases
|
||||||
|
|
||||||
|
PROFILE=${PROFILE:-release}
|
||||||
|
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 $BUILD_FLAGS --features test,$FEATURES --locked 'export_bindings_'
|
||||||
|
if [ "$(ls -nd "core/bindings" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID core/bindings && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
fi
|
||||||
@@ -2,12 +2,19 @@
|
|||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
source ./builder-alias.sh
|
||||||
|
|
||||||
set -ea
|
set -ea
|
||||||
shopt -s expand_aliases
|
shopt -s expand_aliases
|
||||||
|
|
||||||
PROFILE=${PROFILE:-release}
|
PROFILE=${PROFILE:-release}
|
||||||
if [ "${PROFILE}" = "release" ]; then
|
if [ "${PROFILE}" = "release" ]; then
|
||||||
BUILD_FLAGS="--release"
|
BUILD_FLAGS="--release"
|
||||||
|
else
|
||||||
|
if [ "$PROFILE" != "debug"]; then
|
||||||
|
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
|
||||||
|
PROFILE=debug
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
if [ -z "$ARCH" ]; then
|
||||||
@@ -23,7 +30,7 @@ if [ "$ARCH" = "riscv64" ]; then
|
|||||||
RUST_ARCH="riscv64gc"
|
RUST_ARCH="riscv64gc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ..
|
cd ../..
|
||||||
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
|
||||||
RUSTFLAGS=""
|
RUSTFLAGS=""
|
||||||
|
|
||||||
@@ -33,4 +40,7 @@ fi
|
|||||||
|
|
||||||
echo "FEATURES=\"$FEATURES\""
|
echo "FEATURES=\"$FEATURES\""
|
||||||
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
||||||
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-tunnel,tunnel,$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
|
||||||
|
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/tunnelbox" | awk '{ print $3 }')" != "$UID" ]; then
|
||||||
|
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
fi
|
||||||
8
core/build/builder-alias.sh
Normal file
8
core/build/builder-alias.sh
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
USE_TTY=
|
||||||
|
if tty -s; then
|
||||||
|
USE_TTY="-it"
|
||||||
|
fi
|
||||||
|
|
||||||
|
alias 'rust-zig-builder'='docker run '"$USE_TTY"' --rm -e "RUSTFLAGS=$RUSTFLAGS" -e "PKG_CONFIG_SYSROOT_DIR=/opt/sysroot/$ARCH" -e PKG_CONFIG_PATH="" -e PKG_CONFIG_LIBDIR="/opt/sysroot/$ARCH/usr/lib/pkgconfig" -e "AWS_LC_SYS_CMAKE_TOOLCHAIN_FILE_riscv64gc_unknown_linux_musl=/root/cmake-overrides/toolchain-riscv64-musl-clang.cmake" -e SCCACHE_GHA_ENABLED -e SCCACHE_GHA_VERSION -e ACTIONS_RESULTS_URL -e ACTIONS_RUNTIME_TOKEN -v "$HOME/.cargo/registry":/usr/local/cargo/registry -v "$HOME/.cargo/git":/usr/local/cargo/git -v "$HOME/.cache/sccache":/root/.cache/sccache -v "$HOME/.cache/cargo-zigbuild:/root/.cache/cargo-zigbuild" -v "$(pwd)":/workdir -w /workdir start9/cargo-zigbuild'
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -e SCCACHE_GHA_ENABLED -e SCCACHE_GHA_VERSION -e ACTIONS_RESULTS_URL -e ACTIONS_RUNTIME_TOKEN -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$HOME/.cache/sccache":/root/.cache/sccache -v "$(pwd)":/home/rust/src -w /home/rust/src -P start9/rust-musl-cross:$ARCH-musl'
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "helpers"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
color-eyre = "0.6.2"
|
|
||||||
futures = "0.3.28"
|
|
||||||
lazy_async_pool = "0.3.3"
|
|
||||||
models = { path = "../models" }
|
|
||||||
pin-project = "1.1.3"
|
|
||||||
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git", branch = "master" }
|
|
||||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
tokio-stream = { version = "0.1.14", features = ["io-util", "sync"] }
|
|
||||||
tracing = "0.1.39"
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
use std::task::Poll;
|
|
||||||
|
|
||||||
use tokio::io::{AsyncRead, ReadBuf};
|
|
||||||
|
|
||||||
#[pin_project::pin_project]
|
|
||||||
pub struct ByteReplacementReader<R> {
|
|
||||||
pub replace: u8,
|
|
||||||
pub with: u8,
|
|
||||||
#[pin]
|
|
||||||
pub inner: R,
|
|
||||||
}
|
|
||||||
impl<R: AsyncRead> AsyncRead for ByteReplacementReader<R> {
|
|
||||||
fn poll_read(
|
|
||||||
self: std::pin::Pin<&mut Self>,
|
|
||||||
cx: &mut std::task::Context<'_>,
|
|
||||||
buf: &mut ReadBuf<'_>,
|
|
||||||
) -> std::task::Poll<std::io::Result<()>> {
|
|
||||||
let this = self.project();
|
|
||||||
match this.inner.poll_read(cx, buf) {
|
|
||||||
Poll::Ready(Ok(())) => {
|
|
||||||
for idx in 0..buf.filled().len() {
|
|
||||||
if buf.filled()[idx] == *this.replace {
|
|
||||||
buf.filled_mut()[idx] = *this.with;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Poll::Ready(Ok(()))
|
|
||||||
}
|
|
||||||
a => a,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
use std::future::Future;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use color_eyre::eyre::{eyre, Context, Error};
|
|
||||||
use futures::future::BoxFuture;
|
|
||||||
use futures::FutureExt;
|
|
||||||
use models::ResultExt;
|
|
||||||
use tokio::fs::File;
|
|
||||||
use tokio::sync::oneshot;
|
|
||||||
use tokio::task::{JoinError, JoinHandle, LocalSet};
|
|
||||||
|
|
||||||
mod byte_replacement_reader;
|
|
||||||
mod rsync;
|
|
||||||
mod script_dir;
|
|
||||||
pub use byte_replacement_reader::*;
|
|
||||||
pub use rsync::*;
|
|
||||||
pub use script_dir::*;
|
|
||||||
|
|
||||||
pub fn const_true() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_tmp_path(path: impl AsRef<Path>) -> Result<PathBuf, Error> {
|
|
||||||
let path = path.as_ref();
|
|
||||||
if let (Some(parent), Some(file_name)) =
|
|
||||||
(path.parent(), path.file_name().and_then(|f| f.to_str()))
|
|
||||||
{
|
|
||||||
Ok(parent.join(format!(".{}.tmp", file_name)))
|
|
||||||
} else {
|
|
||||||
Err(eyre!("invalid path: {}", path.display()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn canonicalize(
|
|
||||||
path: impl AsRef<Path> + Send + Sync,
|
|
||||||
create_parent: bool,
|
|
||||||
) -> Result<PathBuf, Error> {
|
|
||||||
fn create_canonical_folder<'a>(
|
|
||||||
path: impl AsRef<Path> + Send + Sync + 'a,
|
|
||||||
) -> BoxFuture<'a, Result<PathBuf, Error>> {
|
|
||||||
async move {
|
|
||||||
let path = canonicalize(path, true).await?;
|
|
||||||
tokio::fs::create_dir(&path)
|
|
||||||
.await
|
|
||||||
.with_context(|| path.display().to_string())?;
|
|
||||||
Ok(path)
|
|
||||||
}
|
|
||||||
.boxed()
|
|
||||||
}
|
|
||||||
let path = path.as_ref();
|
|
||||||
if tokio::fs::metadata(path).await.is_err() {
|
|
||||||
let parent = path.parent().unwrap_or(Path::new("."));
|
|
||||||
if let Some(file_name) = path.file_name() {
|
|
||||||
if create_parent && tokio::fs::metadata(parent).await.is_err() {
|
|
||||||
return Ok(create_canonical_folder(parent).await?.join(file_name));
|
|
||||||
} else {
|
|
||||||
return Ok(tokio::fs::canonicalize(parent)
|
|
||||||
.await
|
|
||||||
.with_context(|| parent.display().to_string())?
|
|
||||||
.join(file_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tokio::fs::canonicalize(&path)
|
|
||||||
.await
|
|
||||||
.with_context(|| path.display().to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pin_project::pin_project(PinnedDrop)]
|
|
||||||
pub struct NonDetachingJoinHandle<T>(#[pin] JoinHandle<T>);
|
|
||||||
impl<T> NonDetachingJoinHandle<T> {
|
|
||||||
pub async fn wait_for_abort(self) -> Result<T, JoinError> {
|
|
||||||
self.abort();
|
|
||||||
self.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T> From<JoinHandle<T>> for NonDetachingJoinHandle<T> {
|
|
||||||
fn from(t: JoinHandle<T>) -> Self {
|
|
||||||
NonDetachingJoinHandle(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for NonDetachingJoinHandle<T> {
|
|
||||||
type Target = JoinHandle<T>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T> DerefMut for NonDetachingJoinHandle<T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[pin_project::pinned_drop]
|
|
||||||
impl<T> PinnedDrop for NonDetachingJoinHandle<T> {
|
|
||||||
fn drop(self: std::pin::Pin<&mut Self>) {
|
|
||||||
let this = self.project();
|
|
||||||
this.0.into_ref().get_ref().abort()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T> Future for NonDetachingJoinHandle<T> {
|
|
||||||
type Output = Result<T, JoinError>;
|
|
||||||
fn poll(
|
|
||||||
self: std::pin::Pin<&mut Self>,
|
|
||||||
cx: &mut std::task::Context<'_>,
|
|
||||||
) -> std::task::Poll<Self::Output> {
|
|
||||||
let this = self.project();
|
|
||||||
this.0.poll(cx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AtomicFile {
|
|
||||||
tmp_path: PathBuf,
|
|
||||||
path: PathBuf,
|
|
||||||
file: Option<File>,
|
|
||||||
}
|
|
||||||
impl AtomicFile {
|
|
||||||
pub async fn new(
|
|
||||||
path: impl AsRef<Path> + Send + Sync,
|
|
||||||
tmp_path: Option<impl AsRef<Path> + Send + Sync>,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let path = canonicalize(&path, true).await?;
|
|
||||||
let tmp_path = if let Some(tmp_path) = tmp_path {
|
|
||||||
canonicalize(&tmp_path, true).await?
|
|
||||||
} else {
|
|
||||||
to_tmp_path(&path)?
|
|
||||||
};
|
|
||||||
let file = File::create(&tmp_path)
|
|
||||||
.await
|
|
||||||
.with_context(|| tmp_path.display().to_string())?;
|
|
||||||
Ok(Self {
|
|
||||||
tmp_path,
|
|
||||||
path,
|
|
||||||
file: Some(file),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn rollback(mut self) -> Result<(), Error> {
|
|
||||||
drop(self.file.take());
|
|
||||||
tokio::fs::remove_file(&self.tmp_path)
|
|
||||||
.await
|
|
||||||
.with_context(|| format!("rm {}", self.tmp_path.display()))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn save(mut self) -> Result<(), Error> {
|
|
||||||
use tokio::io::AsyncWriteExt;
|
|
||||||
if let Some(file) = self.file.as_mut() {
|
|
||||||
file.flush().await?;
|
|
||||||
file.shutdown().await?;
|
|
||||||
file.sync_all().await?;
|
|
||||||
}
|
|
||||||
drop(self.file.take());
|
|
||||||
tokio::fs::rename(&self.tmp_path, &self.path)
|
|
||||||
.await
|
|
||||||
.with_context(|| {
|
|
||||||
format!("mv {} -> {}", self.tmp_path.display(), self.path.display())
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Deref for AtomicFile {
|
|
||||||
type Target = File;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
self.file.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::DerefMut for AtomicFile {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
self.file.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Drop for AtomicFile {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some(file) = self.file.take() {
|
|
||||||
drop(file);
|
|
||||||
let path = std::mem::take(&mut self.tmp_path);
|
|
||||||
tokio::spawn(async move { tokio::fs::remove_file(path).await.log_err() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TimedResource<T: 'static + Send> {
|
|
||||||
handle: NonDetachingJoinHandle<Option<T>>,
|
|
||||||
ready: oneshot::Sender<()>,
|
|
||||||
}
|
|
||||||
impl<T: 'static + Send> TimedResource<T> {
|
|
||||||
pub fn new(resource: T, timer: Duration) -> Self {
|
|
||||||
let (send, recv) = oneshot::channel();
|
|
||||||
let handle = tokio::spawn(async move {
|
|
||||||
tokio::select! {
|
|
||||||
_ = tokio::time::sleep(timer) => {
|
|
||||||
drop(resource);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
_ = recv => Some(resource),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Self {
|
|
||||||
handle: handle.into(),
|
|
||||||
ready: send,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_with_destructor<
|
|
||||||
Fn: FnOnce(T) -> Fut + Send + 'static,
|
|
||||||
Fut: Future<Output = ()> + Send,
|
|
||||||
>(
|
|
||||||
resource: T,
|
|
||||||
timer: Duration,
|
|
||||||
destructor: Fn,
|
|
||||||
) -> Self {
|
|
||||||
let (send, recv) = oneshot::channel();
|
|
||||||
let handle = tokio::spawn(async move {
|
|
||||||
tokio::select! {
|
|
||||||
_ = tokio::time::sleep(timer) => {
|
|
||||||
destructor(resource).await;
|
|
||||||
None
|
|
||||||
},
|
|
||||||
_ = recv => Some(resource),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Self {
|
|
||||||
handle: handle.into(),
|
|
||||||
ready: send,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get(self) -> Option<T> {
|
|
||||||
let _ = self.ready.send(());
|
|
||||||
self.handle.await.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_timed_out(&self) -> bool {
|
|
||||||
self.ready.is_closed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn spawn_local<
|
|
||||||
T: 'static + Send,
|
|
||||||
F: FnOnce() -> Fut + Send + 'static,
|
|
||||||
Fut: Future<Output = T> + 'static,
|
|
||||||
>(
|
|
||||||
fut: F,
|
|
||||||
) -> NonDetachingJoinHandle<T> {
|
|
||||||
let (send, recv) = tokio::sync::oneshot::channel();
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
tokio::runtime::Builder::new_current_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
.block_on(async move {
|
|
||||||
let set = LocalSet::new();
|
|
||||||
send.send(set.spawn_local(fut()).into())
|
|
||||||
.unwrap_or_else(|_| unreachable!());
|
|
||||||
set.await
|
|
||||||
})
|
|
||||||
});
|
|
||||||
recv.await.unwrap()
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use color_eyre::Report;
|
|
||||||
use models::InterfaceId;
|
|
||||||
use models::PackageId;
|
|
||||||
use serde_json::Value;
|
|
||||||
use tokio::sync::mpsc;
|
|
||||||
|
|
||||||
pub struct RuntimeDropped;
|
|
||||||
|
|
||||||
pub struct Callback {
|
|
||||||
id: Arc<String>,
|
|
||||||
sender: mpsc::UnboundedSender<(Arc<String>, Vec<Value>)>,
|
|
||||||
}
|
|
||||||
impl Callback {
|
|
||||||
pub fn new(id: String, sender: mpsc::UnboundedSender<(Arc<String>, Vec<Value>)>) -> Self {
|
|
||||||
Self {
|
|
||||||
id: Arc::new(id),
|
|
||||||
sender,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn is_listening(&self) -> bool {
|
|
||||||
self.sender.is_closed()
|
|
||||||
}
|
|
||||||
pub fn call(&self, args: Vec<Value>) -> Result<(), RuntimeDropped> {
|
|
||||||
self.sender
|
|
||||||
.send((self.id.clone(), args))
|
|
||||||
.map_err(|_| RuntimeDropped)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct AddressSchemaOnion {
|
|
||||||
pub id: InterfaceId,
|
|
||||||
pub external_port: u16,
|
|
||||||
}
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct AddressSchemaLocal {
|
|
||||||
pub id: InterfaceId,
|
|
||||||
pub external_port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct Address(pub String);
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct Domain;
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct Name;
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
pub trait OsApi: Send + Sync + 'static {
|
|
||||||
async fn get_service_config(
|
|
||||||
&self,
|
|
||||||
id: PackageId,
|
|
||||||
path: &str,
|
|
||||||
callback: Option<Callback>,
|
|
||||||
) -> Result<Vec<Value>, Report>;
|
|
||||||
|
|
||||||
async fn bind_local(
|
|
||||||
&self,
|
|
||||||
internal_port: u16,
|
|
||||||
address_schema: AddressSchemaLocal,
|
|
||||||
) -> Result<Address, Report>;
|
|
||||||
async fn bind_onion(
|
|
||||||
&self,
|
|
||||||
internal_port: u16,
|
|
||||||
address_schema: AddressSchemaOnion,
|
|
||||||
) -> Result<Address, Report>;
|
|
||||||
|
|
||||||
async fn unbind_local(&self, id: InterfaceId, external: u16) -> Result<(), Report>;
|
|
||||||
async fn unbind_onion(&self, id: InterfaceId, external: u16) -> Result<(), Report>;
|
|
||||||
fn set_started(&self) -> Result<(), Report>;
|
|
||||||
async fn restart(&self) -> Result<(), Report>;
|
|
||||||
async fn start(&self) -> Result<(), Report>;
|
|
||||||
async fn stop(&self) -> Result<(), Report>;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use models::{PackageId, VersionString};
|
|
||||||
|
|
||||||
pub const PKG_SCRIPT_DIR: &str = "package-data/scripts";
|
|
||||||
|
|
||||||
pub fn script_dir<P: AsRef<Path>>(
|
|
||||||
datadir: P,
|
|
||||||
pkg_id: &PackageId,
|
|
||||||
version: &VersionString,
|
|
||||||
) -> PathBuf {
|
|
||||||
datadir
|
|
||||||
.as_ref()
|
|
||||||
.join(&*PKG_SCRIPT_DIR)
|
|
||||||
.join(pkg_id)
|
|
||||||
.join(version.as_str())
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
|
||||||
|
|
||||||
set -ea
|
|
||||||
shopt -s expand_aliases
|
|
||||||
|
|
||||||
web="../web/dist/static"
|
|
||||||
[ -d "$web" ] || mkdir -p "$web"
|
|
||||||
|
|
||||||
if [ -z "$PLATFORM" ]; then
|
|
||||||
PLATFORM=$(uname -m)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$PLATFORM" = "arm64" ]; then
|
|
||||||
PLATFORM="aarch64"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cargo install --path=./startos --no-default-features --features=cli,docker --bin start-cli --locked
|
|
||||||
5343
core/locales/i18n.yaml
Normal file
5343
core/locales/i18n.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,46 +0,0 @@
|
|||||||
[package]
|
|
||||||
edition = "2021"
|
|
||||||
name = "models"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[features]
|
|
||||||
arti = ["arti-client"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
arti-client = { version = "0.33", default-features = false, git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
|
|
||||||
axum = "0.8.4"
|
|
||||||
base64 = "0.22.1"
|
|
||||||
color-eyre = "0.6.2"
|
|
||||||
ed25519-dalek = { version = "2.0.0", features = ["serde"] }
|
|
||||||
exver = { version = "0.2.0", git = "https://github.com/Start9Labs/exver-rs.git", features = [
|
|
||||||
"serde",
|
|
||||||
] }
|
|
||||||
gpt = "4.1.0"
|
|
||||||
ipnet = "2.8.0"
|
|
||||||
lazy_static = "1.4"
|
|
||||||
lettre = { version = "0.11", default-features = false }
|
|
||||||
mbrman = "0.6.0"
|
|
||||||
miette = "7.6.0"
|
|
||||||
num_enum = "0.7.1"
|
|
||||||
openssl = { version = "0.10.57", features = ["vendored"] }
|
|
||||||
patch-db = { version = "*", path = "../../patch-db/patch-db", features = [
|
|
||||||
"trace",
|
|
||||||
] }
|
|
||||||
rand = "0.9.1"
|
|
||||||
regex = "1.10.2"
|
|
||||||
reqwest = "0.12"
|
|
||||||
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git", branch = "master" }
|
|
||||||
rustls = "0.23"
|
|
||||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
ssh-key = "0.6.2"
|
|
||||||
thiserror = "2.0"
|
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
torut = "0.2.1"
|
|
||||||
tracing = "0.1.39"
|
|
||||||
ts-rs = "9"
|
|
||||||
typeid = "1"
|
|
||||||
yasi = { version = "0.1.6", features = ["serde", "ts-rs"] }
|
|
||||||
zbus = "5"
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
mod clap;
|
|
||||||
mod data_url;
|
|
||||||
mod errors;
|
|
||||||
mod id;
|
|
||||||
mod mime;
|
|
||||||
mod procedure_name;
|
|
||||||
mod version;
|
|
||||||
|
|
||||||
pub use clap::*;
|
|
||||||
pub use data_url::*;
|
|
||||||
pub use errors::*;
|
|
||||||
pub use id::*;
|
|
||||||
pub use mime::*;
|
|
||||||
pub use procedure_name::*;
|
|
||||||
pub use version::*;
|
|
||||||
@@ -2,12 +2,19 @@
|
|||||||
|
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
|
||||||
|
source ./build/builder-alias.sh
|
||||||
|
|
||||||
set -ea
|
set -ea
|
||||||
shopt -s expand_aliases
|
shopt -s expand_aliases
|
||||||
|
|
||||||
PROFILE=${PROFILE:-release}
|
PROFILE=${PROFILE:-release}
|
||||||
if [ "${PROFILE}" = "release" ]; then
|
if [ "${PROFILE}" = "release" ]; then
|
||||||
BUILD_FLAGS="--release"
|
BUILD_FLAGS="--release"
|
||||||
|
else
|
||||||
|
if [ "$PROFILE" != "debug"]; then
|
||||||
|
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
|
||||||
|
PROFILE=debug
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
if [ -z "$ARCH" ]; then
|
||||||
@@ -31,8 +38,8 @@ if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
|
|||||||
RUSTFLAGS="--cfg tokio_unstable"
|
RUSTFLAGS="--cfg tokio_unstable"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source ./core/builder-alias.sh
|
|
||||||
|
|
||||||
echo "FEATURES=\"$FEATURES\""
|
echo "FEATURES=\"$FEATURES\""
|
||||||
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
echo "RUSTFLAGS=\"$RUSTFLAGS\""
|
||||||
cross test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=test,$FEATURES --workspace --locked --target=$ARCH-unknown-linux-musl -- --skip export_bindings_
|
rust-zig-builder cargo test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=test,$FEATURES --workspace --locked --lib -- --skip export_bindings_
|
||||||
|
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /usr/local/cargo"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use openssl::x509::X509;
|
|||||||
|
|
||||||
use crate::db::model::DatabaseModel;
|
use crate::db::model::DatabaseModel;
|
||||||
use crate::hostname::{Hostname, generate_hostname, generate_id};
|
use crate::hostname::{Hostname, generate_hostname, generate_id};
|
||||||
use crate::net::ssl::{generate_key, make_root_cert};
|
use crate::net::ssl::{gen_nistp256, make_root_cert};
|
||||||
use crate::net::tor::TorSecretKey;
|
use crate::net::tor::TorSecretKey;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::serde::Pem;
|
use crate::util::serde::Pem;
|
||||||
@@ -37,7 +37,7 @@ impl AccountInfo {
|
|||||||
let server_id = generate_id();
|
let server_id = generate_id();
|
||||||
let hostname = generate_hostname();
|
let hostname = generate_hostname();
|
||||||
let tor_key = vec![TorSecretKey::generate()];
|
let tor_key = vec![TorSecretKey::generate()];
|
||||||
let root_ca_key = generate_key()?;
|
let root_ca_key = gen_nistp256()?;
|
||||||
let root_ca_cert = make_root_cert(&root_ca_key, &hostname, start_time)?;
|
let root_ca_cert = make_root_cert(&root_ca_key, &hostname, start_time)?;
|
||||||
let ssh_key = ssh_key::PrivateKey::from(ssh_key::private::Ed25519Keypair::random(
|
let ssh_key = ssh_key::PrivateKey::from(ssh_key::private::Ed25519Keypair::random(
|
||||||
&mut ssh_key::rand_core::OsRng::default(),
|
&mut ssh_key::rand_core::OsRng::default(),
|
||||||
@@ -128,7 +128,7 @@ impl AccountInfo {
|
|||||||
cert_store
|
cert_store
|
||||||
.as_root_cert_mut()
|
.as_root_cert_mut()
|
||||||
.ser(Pem::new_ref(&self.root_ca_cert))?;
|
.ser(Pem::new_ref(&self.root_ca_cert))?;
|
||||||
let int_key = crate::net::ssl::generate_key()?;
|
let int_key = crate::net::ssl::gen_nistp256()?;
|
||||||
let int_cert =
|
let int_cert =
|
||||||
crate::net::ssl::make_int_cert((&self.root_ca_key, &self.root_ca_cert), &int_key)?;
|
crate::net::ssl::make_int_cert((&self.root_ca_key, &self.root_ca_cert), &int_key)?;
|
||||||
cert_store.as_int_key_mut().ser(&Pem(int_key))?;
|
cert_store.as_int_key_mut().ser(&Pem(int_key))?;
|
||||||
@@ -1,34 +1,21 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use clap::{CommandFactory, FromArgMatches, Parser};
|
use clap::{CommandFactory, FromArgMatches, Parser};
|
||||||
pub use models::ActionId;
|
|
||||||
use models::{PackageId, ReplayId};
|
|
||||||
use qrcode::QrCode;
|
use qrcode::QrCode;
|
||||||
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
|
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
|
pub use crate::ActionId;
|
||||||
use crate::context::{CliContext, RpcContext};
|
use crate::context::{CliContext, RpcContext};
|
||||||
use crate::db::model::package::TaskSeverity;
|
use crate::db::model::package::TaskSeverity;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rpc_continuations::Guid;
|
use crate::rpc_continuations::Guid;
|
||||||
use crate::util::serde::{
|
use crate::util::serde::{
|
||||||
display_serializable, HandlerExtSerde, StdinDeserializable, WithIoFormat,
|
HandlerExtSerde, StdinDeserializable, WithIoFormat, display_serializable,
|
||||||
};
|
};
|
||||||
|
use crate::{PackageId, ReplayId};
|
||||||
#[test]
|
|
||||||
fn export_bindings_action() {
|
|
||||||
use crate::db::model::package::{ActionMetadata, Task};
|
|
||||||
|
|
||||||
const OUT_DIR: &str = "./bindings/action";
|
|
||||||
|
|
||||||
ActionId::export_all_to(OUT_DIR).unwrap();
|
|
||||||
ActionInput::export_all_to(OUT_DIR).unwrap();
|
|
||||||
ActionResult::export_all_to(OUT_DIR).unwrap();
|
|
||||||
ActionMetadata::export_all_to(OUT_DIR).unwrap();
|
|
||||||
Task::export_all_to(OUT_DIR).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn action_api<C: Context>() -> ParentHandler<C> {
|
pub fn action_api<C: Context>() -> ParentHandler<C> {
|
||||||
ParentHandler::new()
|
ParentHandler::new()
|
||||||
@@ -36,7 +23,7 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
|
|||||||
"get-input",
|
"get-input",
|
||||||
from_fn_async(get_action_input)
|
from_fn_async(get_action_input)
|
||||||
.with_display_serializable()
|
.with_display_serializable()
|
||||||
.with_about("Get action input spec")
|
.with_about("about.get-action-input-spec")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
@@ -49,19 +36,20 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.with_about("Run service action")
|
.with_about("about.run-service-action")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"clear-task",
|
"clear-task",
|
||||||
from_fn_async(clear_task)
|
from_fn_async(clear_task)
|
||||||
.no_display()
|
.no_display()
|
||||||
.with_about("Clear a service task")
|
.with_about("about.clear-service-task")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
|
||||||
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ActionInput {
|
pub struct ActionInput {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -75,7 +63,9 @@ pub struct ActionInput {
|
|||||||
#[derive(Deserialize, Serialize, TS, Parser)]
|
#[derive(Deserialize, Serialize, TS, Parser)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct GetActionInputParams {
|
pub struct GetActionInputParams {
|
||||||
|
#[arg(help = "help.arg.package-id")]
|
||||||
pub package_id: PackageId,
|
pub package_id: PackageId,
|
||||||
|
#[arg(help = "help.arg.action-id")]
|
||||||
pub action_id: ActionId,
|
pub action_id: ActionId,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +88,7 @@ pub async fn get_action_input(
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, TS)]
|
#[derive(Debug, Serialize, Deserialize, TS)]
|
||||||
#[serde(tag = "version")]
|
#[serde(tag = "version")]
|
||||||
|
#[ts(export)]
|
||||||
pub enum ActionResult {
|
pub enum ActionResult {
|
||||||
#[serde(rename = "0")]
|
#[serde(rename = "0")]
|
||||||
V0(ActionResultV0),
|
V0(ActionResultV0),
|
||||||
@@ -291,8 +282,11 @@ pub struct RunActionParams {
|
|||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct CliRunActionParams {
|
struct CliRunActionParams {
|
||||||
|
#[arg(help = "help.arg.package-id")]
|
||||||
pub package_id: PackageId,
|
pub package_id: PackageId,
|
||||||
|
#[arg(help = "help.arg.event-id")]
|
||||||
pub event_id: Option<Guid>,
|
pub event_id: Option<Guid>,
|
||||||
|
#[arg(help = "help.arg.action-id")]
|
||||||
pub action_id: ActionId,
|
pub action_id: ActionId,
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub input: StdinDeserializable<Option<Value>>,
|
pub input: StdinDeserializable<Option<Value>>,
|
||||||
@@ -371,9 +365,11 @@ pub async fn run_action(
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[command(rename_all = "kebab-case")]
|
#[command(rename_all = "kebab-case")]
|
||||||
pub struct ClearTaskParams {
|
pub struct ClearTaskParams {
|
||||||
|
#[arg(help = "help.arg.package-id")]
|
||||||
pub package_id: PackageId,
|
pub package_id: PackageId,
|
||||||
|
#[arg(help = "help.arg.replay-id")]
|
||||||
pub replay_id: ReplayId,
|
pub replay_id: ReplayId,
|
||||||
#[arg(long)]
|
#[arg(long, help = "help.arg.force-clear-task")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
}
|
}
|
||||||
@@ -14,8 +14,8 @@ use tracing::instrument;
|
|||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
use crate::context::{CliContext, RpcContext};
|
use crate::context::{CliContext, RpcContext};
|
||||||
use crate::middleware::auth::{
|
use crate::middleware::auth::session::{
|
||||||
AsLogoutSessionId, AuthContext, HasLoggedOutSessions, HashSessionToken, LoginRes,
|
AsLogoutSessionId, HasLoggedOutSessions, HashSessionToken, LoginRes, SessionAuthContext,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::crypto::EncryptedWire;
|
use crate::util::crypto::EncryptedWire;
|
||||||
@@ -51,7 +51,10 @@ pub async fn write_shadow(password: &str) -> Result<(), Error> {
|
|||||||
match line.split_once(":") {
|
match line.split_once(":") {
|
||||||
Some((user, rest)) if user == "start9" || user == "kiosk" => {
|
Some((user, rest)) if user == "start9" || user == "kiosk" => {
|
||||||
let (_, rest) = rest.split_once(":").ok_or_else(|| {
|
let (_, rest) = rest.split_once(":").ok_or_else(|| {
|
||||||
Error::new(eyre!("malformed /etc/shadow"), ErrorKind::ParseSysInfo)
|
Error::new(
|
||||||
|
eyre!("{}", t!("auth.malformed-etc-shadow")),
|
||||||
|
ErrorKind::ParseSysInfo,
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
shadow_file
|
shadow_file
|
||||||
.write_all(format!("{user}:{hash}:{rest}\n").as_bytes())
|
.write_all(format!("{user}:{hash}:{rest}\n").as_bytes())
|
||||||
@@ -70,6 +73,7 @@ pub async fn write_shadow(password: &str) -> Result<(), Error> {
|
|||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, TS)]
|
#[derive(Clone, Serialize, Deserialize, TS)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
|
#[ts(export)]
|
||||||
pub enum PasswordType {
|
pub enum PasswordType {
|
||||||
EncryptedWire(EncryptedWire),
|
EncryptedWire(EncryptedWire),
|
||||||
String(String),
|
String(String),
|
||||||
@@ -80,7 +84,7 @@ impl PasswordType {
|
|||||||
PasswordType::String(x) => Ok(x),
|
PasswordType::String(x) => Ok(x),
|
||||||
PasswordType::EncryptedWire(x) => x.decrypt(current_secret).ok_or_else(|| {
|
PasswordType::EncryptedWire(x) => x.decrypt(current_secret).ok_or_else(|| {
|
||||||
Error::new(
|
Error::new(
|
||||||
color_eyre::eyre::eyre!("Couldn't decode password"),
|
color_eyre::eyre::eyre!("{}", t!("auth.couldnt-decode-password")),
|
||||||
crate::ErrorKind::Unknown,
|
crate::ErrorKind::Unknown,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
@@ -109,7 +113,7 @@ impl std::str::FromStr for PasswordType {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn auth<C: Context, AC: AuthContext>() -> ParentHandler<C>
|
pub fn auth<C: Context, AC: SessionAuthContext>() -> ParentHandler<C>
|
||||||
where
|
where
|
||||||
CliContext: CallRemote<AC>,
|
CliContext: CallRemote<AC>,
|
||||||
{
|
{
|
||||||
@@ -124,19 +128,19 @@ where
|
|||||||
"login",
|
"login",
|
||||||
from_fn_async(cli_login::<AC>)
|
from_fn_async(cli_login::<AC>)
|
||||||
.no_display()
|
.no_display()
|
||||||
.with_about("Log in a new auth session"),
|
.with_about("about.login-new-auth-session"),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"logout",
|
"logout",
|
||||||
from_fn_async(logout::<AC>)
|
from_fn_async(logout::<AC>)
|
||||||
.with_metadata("get_session", Value::Bool(true))
|
.with_metadata("get_session", Value::Bool(true))
|
||||||
.no_display()
|
.no_display()
|
||||||
.with_about("Log out of current auth session")
|
.with_about("about.logout-current-auth-session")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"session",
|
"session",
|
||||||
session::<C, AC>().with_about("List or kill auth sessions"),
|
session::<C, AC>().with_about("about.list-or-kill-auth-sessions"),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"reset-password",
|
"reset-password",
|
||||||
@@ -146,7 +150,15 @@ where
|
|||||||
"reset-password",
|
"reset-password",
|
||||||
from_fn_async(cli_reset_password)
|
from_fn_async(cli_reset_password)
|
||||||
.no_display()
|
.no_display()
|
||||||
.with_about("Reset password"),
|
.with_about("about.reset-password"),
|
||||||
|
)
|
||||||
|
.subcommand(
|
||||||
|
"get-pubkey",
|
||||||
|
from_fn_async(get_pubkey)
|
||||||
|
.with_metadata("authenticated", Value::Bool(false))
|
||||||
|
.no_display()
|
||||||
|
.with_about("about.get-pubkey-from-server")
|
||||||
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +176,7 @@ fn gen_pwd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
async fn cli_login<C: AuthContext>(
|
async fn cli_login<C: SessionAuthContext>(
|
||||||
HandlerArgs {
|
HandlerArgs {
|
||||||
context: ctx,
|
context: ctx,
|
||||||
parent_method,
|
parent_method,
|
||||||
@@ -175,7 +187,11 @@ async fn cli_login<C: AuthContext>(
|
|||||||
where
|
where
|
||||||
CliContext: CallRemote<C>,
|
CliContext: CallRemote<C>,
|
||||||
{
|
{
|
||||||
let password = rpassword::prompt_password("Password: ")?;
|
let password = if let Ok(password) = std::env::var("PASSWORD") {
|
||||||
|
password
|
||||||
|
} else {
|
||||||
|
rpassword::prompt_password("Password: ")?
|
||||||
|
};
|
||||||
|
|
||||||
ctx.call_remote::<C>(
|
ctx.call_remote::<C>(
|
||||||
&parent_method.into_iter().chain(method).join("."),
|
&parent_method.into_iter().chain(method).join("."),
|
||||||
@@ -195,18 +211,19 @@ pub fn check_password(hash: &str, password: &str) -> Result<(), Error> {
|
|||||||
ensure_code!(
|
ensure_code!(
|
||||||
argon2::verify_encoded(&hash, password.as_bytes()).map_err(|_| {
|
argon2::verify_encoded(&hash, password.as_bytes()).map_err(|_| {
|
||||||
Error::new(
|
Error::new(
|
||||||
eyre!("Password Incorrect"),
|
eyre!("{}", t!("auth.password-incorrect")),
|
||||||
crate::ErrorKind::IncorrectPassword,
|
crate::ErrorKind::IncorrectPassword,
|
||||||
)
|
)
|
||||||
})?,
|
})?,
|
||||||
crate::ErrorKind::IncorrectPassword,
|
crate::ErrorKind::IncorrectPassword,
|
||||||
"Password Incorrect"
|
t!("auth.password-incorrect")
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, TS)]
|
#[derive(Deserialize, Serialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export)]
|
||||||
pub struct LoginParams {
|
pub struct LoginParams {
|
||||||
password: String,
|
password: String,
|
||||||
#[ts(skip)]
|
#[ts(skip)]
|
||||||
@@ -217,7 +234,7 @@ pub struct LoginParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn login_impl<C: AuthContext>(
|
pub async fn login_impl<C: SessionAuthContext>(
|
||||||
ctx: C,
|
ctx: C,
|
||||||
LoginParams {
|
LoginParams {
|
||||||
password,
|
password,
|
||||||
@@ -273,7 +290,7 @@ pub struct LogoutParams {
|
|||||||
session: InternedString,
|
session: InternedString,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn logout<C: AuthContext>(
|
pub async fn logout<C: SessionAuthContext>(
|
||||||
ctx: C,
|
ctx: C,
|
||||||
LogoutParams { session }: LogoutParams,
|
LogoutParams { session }: LogoutParams,
|
||||||
) -> Result<Option<HasLoggedOutSessions>, Error> {
|
) -> Result<Option<HasLoggedOutSessions>, Error> {
|
||||||
@@ -284,6 +301,7 @@ pub async fn logout<C: AuthContext>(
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export)]
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
#[ts(type = "string")]
|
#[ts(type = "string")]
|
||||||
pub logged_in: DateTime<Utc>,
|
pub logged_in: DateTime<Utc>,
|
||||||
@@ -294,13 +312,14 @@ pub struct Session {
|
|||||||
|
|
||||||
#[derive(Deserialize, Serialize, TS)]
|
#[derive(Deserialize, Serialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export)]
|
||||||
pub struct SessionList {
|
pub struct SessionList {
|
||||||
#[ts(type = "string | null")]
|
#[ts(type = "string | null")]
|
||||||
current: Option<InternedString>,
|
current: Option<InternedString>,
|
||||||
sessions: Sessions,
|
sessions: Sessions,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session<C: Context, AC: AuthContext>() -> ParentHandler<C>
|
pub fn session<C: Context, AC: SessionAuthContext>() -> ParentHandler<C>
|
||||||
where
|
where
|
||||||
CliContext: CallRemote<AC>,
|
CliContext: CallRemote<AC>,
|
||||||
{
|
{
|
||||||
@@ -311,14 +330,14 @@ where
|
|||||||
.with_metadata("get_session", Value::Bool(true))
|
.with_metadata("get_session", Value::Bool(true))
|
||||||
.with_display_serializable()
|
.with_display_serializable()
|
||||||
.with_custom_display_fn(|handle, result| display_sessions(handle.params, result))
|
.with_custom_display_fn(|handle, result| display_sessions(handle.params, result))
|
||||||
.with_about("Display all auth sessions")
|
.with_about("about.display-all-auth-sessions")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"kill",
|
"kill",
|
||||||
from_fn_async(kill::<AC>)
|
from_fn_async(kill::<AC>)
|
||||||
.no_display()
|
.no_display()
|
||||||
.with_about("Terminate existing auth session(s)")
|
.with_about("about.terminate-auth-sessions")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -367,7 +386,7 @@ pub struct ListParams {
|
|||||||
|
|
||||||
// #[command(display(display_sessions))]
|
// #[command(display(display_sessions))]
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn list<C: AuthContext>(
|
pub async fn list<C: SessionAuthContext>(
|
||||||
ctx: C,
|
ctx: C,
|
||||||
ListParams { session, .. }: ListParams,
|
ListParams { session, .. }: ListParams,
|
||||||
) -> Result<SessionList, Error> {
|
) -> Result<SessionList, Error> {
|
||||||
@@ -383,7 +402,7 @@ pub async fn list<C: AuthContext>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct KillSessionId(InternedString);
|
struct KillSessionId(InternedString);
|
||||||
|
|
||||||
impl KillSessionId {
|
impl KillSessionId {
|
||||||
@@ -402,11 +421,15 @@ impl AsLogoutSessionId for KillSessionId {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[command(rename_all = "kebab-case")]
|
#[command(rename_all = "kebab-case")]
|
||||||
pub struct KillParams {
|
pub struct KillParams {
|
||||||
|
#[arg(help = "help.arg.session-ids")]
|
||||||
ids: Vec<String>,
|
ids: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn kill<C: AuthContext>(ctx: C, KillParams { ids }: KillParams) -> Result<(), Error> {
|
pub async fn kill<C: SessionAuthContext>(
|
||||||
|
ctx: C,
|
||||||
|
KillParams { ids }: KillParams,
|
||||||
|
) -> Result<(), Error> {
|
||||||
HasLoggedOutSessions::new(ids.into_iter().map(KillSessionId::new), &ctx).await?;
|
HasLoggedOutSessions::new(ids.into_iter().map(KillSessionId::new), &ctx).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -415,7 +438,9 @@ pub async fn kill<C: AuthContext>(ctx: C, KillParams { ids }: KillParams) -> Res
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[command(rename_all = "kebab-case")]
|
#[command(rename_all = "kebab-case")]
|
||||||
pub struct ResetPasswordParams {
|
pub struct ResetPasswordParams {
|
||||||
|
#[arg(help = "help.arg.old-password")]
|
||||||
old_password: Option<PasswordType>,
|
old_password: Option<PasswordType>,
|
||||||
|
#[arg(help = "help.arg.new-password")]
|
||||||
new_password: Option<PasswordType>,
|
new_password: Option<PasswordType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,13 +453,13 @@ async fn cli_reset_password(
|
|||||||
..
|
..
|
||||||
}: HandlerArgs<CliContext>,
|
}: HandlerArgs<CliContext>,
|
||||||
) -> Result<(), RpcError> {
|
) -> Result<(), RpcError> {
|
||||||
let old_password = rpassword::prompt_password("Current Password: ")?;
|
let old_password = rpassword::prompt_password(&t!("auth.prompt-current-password"))?;
|
||||||
|
|
||||||
let new_password = {
|
let new_password = {
|
||||||
let new_password = rpassword::prompt_password("New Password: ")?;
|
let new_password = rpassword::prompt_password(&t!("auth.prompt-new-password"))?;
|
||||||
if new_password != rpassword::prompt_password("Confirm: ")? {
|
if new_password != rpassword::prompt_password(&t!("auth.prompt-confirm"))? {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
eyre!("Passwords do not match"),
|
eyre!("{}", t!("auth.passwords-do-not-match")),
|
||||||
crate::ErrorKind::IncorrectPassword,
|
crate::ErrorKind::IncorrectPassword,
|
||||||
)
|
)
|
||||||
.into());
|
.into());
|
||||||
@@ -467,7 +492,7 @@ pub async fn reset_password_impl(
|
|||||||
.with_kind(crate::ErrorKind::IncorrectPassword)?
|
.with_kind(crate::ErrorKind::IncorrectPassword)?
|
||||||
{
|
{
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
eyre!("Incorrect Password"),
|
eyre!("{}", t!("auth.password-incorrect")),
|
||||||
crate::ErrorKind::IncorrectPassword,
|
crate::ErrorKind::IncorrectPassword,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -5,9 +5,7 @@ use std::sync::Arc;
|
|||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use color_eyre::eyre::eyre;
|
use color_eyre::eyre::eyre;
|
||||||
use helpers::AtomicFile;
|
|
||||||
use imbl::OrdSet;
|
use imbl::OrdSet;
|
||||||
use models::PackageId;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -15,6 +13,7 @@ use ts_rs::TS;
|
|||||||
|
|
||||||
use super::PackageBackupReport;
|
use super::PackageBackupReport;
|
||||||
use super::target::{BackupTargetId, PackageBackupInfo};
|
use super::target::{BackupTargetId, PackageBackupInfo};
|
||||||
|
use crate::PackageId;
|
||||||
use crate::backup::os::OsBackup;
|
use crate::backup::os::OsBackup;
|
||||||
use crate::backup::{BackupReport, ServerBackupReport};
|
use crate::backup::{BackupReport, ServerBackupReport};
|
||||||
use crate::context::RpcContext;
|
use crate::context::RpcContext;
|
||||||
@@ -23,10 +22,10 @@ use crate::db::model::{Database, DatabaseModel};
|
|||||||
use crate::disk::mount::backup::BackupMountGuard;
|
use crate::disk::mount::backup::BackupMountGuard;
|
||||||
use crate::disk::mount::filesystem::ReadWrite;
|
use crate::disk::mount::filesystem::ReadWrite;
|
||||||
use crate::disk::mount::guard::{GenericMountGuard, TmpMountGuard};
|
use crate::disk::mount::guard::{GenericMountGuard, TmpMountGuard};
|
||||||
use crate::middleware::auth::AuthContext;
|
use crate::middleware::auth::session::SessionAuthContext;
|
||||||
use crate::notifications::{NotificationLevel, notify};
|
use crate::notifications::{NotificationLevel, notify};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::io::dir_copy;
|
use crate::util::io::{AtomicFile, dir_copy};
|
||||||
use crate::util::serde::IoFormat;
|
use crate::util::serde::IoFormat;
|
||||||
use crate::version::VersionT;
|
use crate::version::VersionT;
|
||||||
|
|
||||||
@@ -34,11 +33,13 @@ use crate::version::VersionT;
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[command(rename_all = "kebab-case")]
|
#[command(rename_all = "kebab-case")]
|
||||||
pub struct BackupParams {
|
pub struct BackupParams {
|
||||||
|
#[arg(help = "help.arg.backup-target-id")]
|
||||||
target_id: BackupTargetId,
|
target_id: BackupTargetId,
|
||||||
#[arg(long = "old-password")]
|
#[arg(long = "old-password", help = "help.arg.old-backup-password")]
|
||||||
old_password: Option<crate::auth::PasswordType>,
|
old_password: Option<crate::auth::PasswordType>,
|
||||||
#[arg(long = "package-ids")]
|
#[arg(long = "package-ids", help = "help.arg.package-ids-to-backup")]
|
||||||
package_ids: Option<Vec<PackageId>>,
|
package_ids: Option<Vec<PackageId>>,
|
||||||
|
#[arg(help = "help.arg.backup-password")]
|
||||||
password: crate::auth::PasswordType,
|
password: crate::auth::PasswordType,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +71,8 @@ impl BackupStatusGuard {
|
|||||||
db,
|
db,
|
||||||
None,
|
None,
|
||||||
NotificationLevel::Success,
|
NotificationLevel::Success,
|
||||||
"Backup Complete".to_owned(),
|
t!("backup.bulk.complete-title").to_string(),
|
||||||
"Your backup has completed".to_owned(),
|
t!("backup.bulk.complete-message").to_string(),
|
||||||
BackupReport {
|
BackupReport {
|
||||||
server: ServerBackupReport {
|
server: ServerBackupReport {
|
||||||
attempted: true,
|
attempted: true,
|
||||||
@@ -89,9 +90,8 @@ impl BackupStatusGuard {
|
|||||||
db,
|
db,
|
||||||
None,
|
None,
|
||||||
NotificationLevel::Warning,
|
NotificationLevel::Warning,
|
||||||
"Backup Complete".to_owned(),
|
t!("backup.bulk.complete-title").to_string(),
|
||||||
"Your backup has completed, but some package(s) failed to backup"
|
t!("backup.bulk.complete-with-failures").to_string(),
|
||||||
.to_owned(),
|
|
||||||
BackupReport {
|
BackupReport {
|
||||||
server: ServerBackupReport {
|
server: ServerBackupReport {
|
||||||
attempted: true,
|
attempted: true,
|
||||||
@@ -104,7 +104,7 @@ impl BackupStatusGuard {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Backup Failed: {}", e);
|
tracing::error!("{}", t!("backup.bulk.failed-error", error = e));
|
||||||
tracing::debug!("{:?}", e);
|
tracing::debug!("{:?}", e);
|
||||||
let err_string = e.to_string();
|
let err_string = e.to_string();
|
||||||
db.mutate(|db| {
|
db.mutate(|db| {
|
||||||
@@ -112,8 +112,8 @@ impl BackupStatusGuard {
|
|||||||
db,
|
db,
|
||||||
None,
|
None,
|
||||||
NotificationLevel::Error,
|
NotificationLevel::Error,
|
||||||
"Backup Failed".to_owned(),
|
t!("backup.bulk.failed-title").to_string(),
|
||||||
"Your backup failed to complete.".to_owned(),
|
t!("backup.bulk.failed-message").to_string(),
|
||||||
BackupReport {
|
BackupReport {
|
||||||
server: ServerBackupReport {
|
server: ServerBackupReport {
|
||||||
attempted: true,
|
attempted: true,
|
||||||
@@ -225,7 +225,7 @@ fn assure_backing_up<'a>(
|
|||||||
.as_backup_progress_mut();
|
.as_backup_progress_mut();
|
||||||
if backing_up.transpose_ref().is_some() {
|
if backing_up.transpose_ref().is_some() {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
eyre!("Server is already backing up!"),
|
eyre!("{}", t!("backup.bulk.already-backing-up")),
|
||||||
ErrorKind::InvalidRequest,
|
ErrorKind::InvalidRequest,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -304,7 +304,7 @@ async fn perform_backup(
|
|||||||
|
|
||||||
let mut backup_guard = Arc::try_unwrap(backup_guard).map_err(|_| {
|
let mut backup_guard = Arc::try_unwrap(backup_guard).map_err(|_| {
|
||||||
Error::new(
|
Error::new(
|
||||||
eyre!("leaked reference to BackupMountGuard"),
|
eyre!("{}", t!("backup.bulk.leaked-reference")),
|
||||||
ErrorKind::Incoherent,
|
ErrorKind::Incoherent,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@@ -312,19 +312,14 @@ async fn perform_backup(
|
|||||||
let ui = ctx.db.peek().await.into_public().into_ui().de()?;
|
let ui = ctx.db.peek().await.into_public().into_ui().de()?;
|
||||||
|
|
||||||
let mut os_backup_file =
|
let mut os_backup_file =
|
||||||
AtomicFile::new(backup_guard.path().join("os-backup.json"), None::<PathBuf>)
|
AtomicFile::new(backup_guard.path().join("os-backup.json"), None::<PathBuf>).await?;
|
||||||
.await
|
|
||||||
.with_kind(ErrorKind::Filesystem)?;
|
|
||||||
os_backup_file
|
os_backup_file
|
||||||
.write_all(&IoFormat::Json.to_vec(&OsBackup {
|
.write_all(&IoFormat::Json.to_vec(&OsBackup {
|
||||||
account: ctx.account.peek(|a| a.clone()),
|
account: ctx.account.peek(|a| a.clone()),
|
||||||
ui,
|
ui,
|
||||||
})?)
|
})?)
|
||||||
.await?;
|
.await?;
|
||||||
os_backup_file
|
os_backup_file.save().await?;
|
||||||
.save()
|
|
||||||
.await
|
|
||||||
.with_kind(ErrorKind::Filesystem)?;
|
|
||||||
|
|
||||||
let luks_folder_old = backup_guard.path().join("luks.old");
|
let luks_folder_old = backup_guard.path().join("luks.old");
|
||||||
if tokio::fs::metadata(&luks_folder_old).await.is_ok() {
|
if tokio::fs::metadata(&luks_folder_old).await.is_ok() {
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
|
||||||
use models::{HostId, PackageId};
|
|
||||||
use reqwest::Url;
|
|
||||||
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async};
|
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::PackageId;
|
||||||
use crate::context::CliContext;
|
use crate::context::CliContext;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::serde::{Base32, Base64};
|
|
||||||
|
|
||||||
pub mod backup_bulk;
|
pub mod backup_bulk;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
@@ -40,12 +37,12 @@ pub fn backup<C: Context>() -> ParentHandler<C> {
|
|||||||
"create",
|
"create",
|
||||||
from_fn_async(backup_bulk::backup_all)
|
from_fn_async(backup_bulk::backup_all)
|
||||||
.no_display()
|
.no_display()
|
||||||
.with_about("Create backup for all packages")
|
.with_about("about.create-backup-all-packages")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"target",
|
"target",
|
||||||
target::target::<C>().with_about("Commands related to a backup target"),
|
target::target::<C>().with_about("about.commands-backup-target"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,17 +51,7 @@ pub fn package_backup<C: Context>() -> ParentHandler<C> {
|
|||||||
"restore",
|
"restore",
|
||||||
from_fn_async(restore::restore_packages_rpc)
|
from_fn_async(restore::restore_packages_rpc)
|
||||||
.no_display()
|
.no_display()
|
||||||
.with_about("Restore package(s) from backup")
|
.with_about("about.restore-packages-from-backup")
|
||||||
.with_call_remote::<CliContext>(),
|
.with_call_remote::<CliContext>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
struct BackupMetadata {
|
|
||||||
pub timestamp: DateTime<Utc>,
|
|
||||||
#[serde(default)]
|
|
||||||
pub network_keys: BTreeMap<HostId, Base64<[u8; 32]>>,
|
|
||||||
#[serde(default)]
|
|
||||||
pub tor_keys: BTreeMap<HostId, Base32<[u8; 64]>>, // DEPRECATED
|
|
||||||
pub registry: Option<Url>,
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user