* add support for idmapped mounts to start-sdk

* misc fixes

* misc fixes

* add default to textarea

* fix iptables masquerade rule

* fix textarea types

* more fixes

* better logging for rsync

* fix tty size

* fix wg conf generation for android

* disable file mounts on dependencies

* mostly there, some styling issues (#3069)

* mostly there, some styling issues

* fix: address comments (#3070)

* fix: address comments

* fix: fix

* show SSL for any address with secure protocol and ssl added

* better sorting and messaging

---------

Co-authored-by: Alex Inkin <alexander@inkin.ru>

* fixes for nextcloud

* allow sidebar navigation during service state traansitions

* wip: x-forwarded headers

* implement x-forwarded-for proxy

* lowercase domain names and fix warning popover bug

* fix http2 websockets

* fix websocket retry behavior

* add arch filters to s9pk pack

* use docker for start-cli install

* add version range to package signer on registry

* fix rcs < 0

* fix user information parsing

* refactor service interface getters

* disable idmaps

* build fixes

* update docker login action

* streamline build

* add start-cli workflow

* rename

* riscv64gc

* fix ui packing

* no default features on cli

* make cli depend on GIT_HASH

* more build fixes

* more build fixes

* interpolate arch within dockerfile

* fix tests

* add launch ui to service page plus other small improvements (#3075)

* add launch ui to service page plus other small improvements

* revert translation disable

* add spinner to service list if service is health and loading

* chore: some visual tune up

* chore: update Taiga UI

---------

Co-authored-by: waterplea <alexander@inkin.ru>

* fix backups

* feat: use arm hosted runners and don't fail when apt package does not exist (#3076)

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>
Co-authored-by: Shadowy Super Coder <musashidisciple@proton.me>
Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com>
Co-authored-by: Alex Inkin <alexander@inkin.ru>
Co-authored-by: Remco Ros <remcoros@live.nl>
This commit is contained in:
Aiden McClelland
2025-12-15 13:30:50 -07:00
committed by GitHub
parent b945243d1a
commit 0430e0f930
148 changed files with 2572 additions and 1761 deletions

View File

@@ -53,10 +53,19 @@ async function bind(
from: string,
to: string,
type: "file" | "directory" | "infer",
idmap: IdMap[],
) {
await prepBind(from, to, type)
await execFile("mount", ["--bind", from, to])
const args = ["--bind"]
if (idmap.length) {
args.push(
`-oX-mount.idmap=${idmap.map((i) => `b:${i.fromId}:${i.toId}:${i.range}`).join(" ")}`,
)
}
await execFile("mount", [...args, from, to])
}
export interface SubContainer<
@@ -137,9 +146,9 @@ export interface SubContainer<
* Want to limit what we can do in a container, so we want to launch a container with a specific image and the mounts.
*/
export class SubContainerOwned<
Manifest extends T.SDKManifest,
Effects extends T.Effects = T.Effects,
>
Manifest extends T.SDKManifest,
Effects extends T.Effects = T.Effects,
>
extends Drop
implements SubContainer<Manifest, Effects>
{
@@ -306,7 +315,7 @@ export class SubContainerOwned<
: "/"
const from = `/media/startos/volumes/${options.volumeId}${subpath}`
await bind(from, path, mount.options.filetype)
await bind(from, path, options.filetype, options.idmap)
} else if (options.type === "assets") {
const subpath = options.subpath
? options.subpath.startsWith("/")
@@ -315,9 +324,9 @@ export class SubContainerOwned<
: "/"
const from = `/media/startos/assets/${subpath}`
await bind(from, path, mount.options.filetype)
await bind(from, path, options.filetype, options.idmap)
} else if (options.type === "pointer") {
await prepBind(null, path, options.filetype)
await prepBind(null, path, "directory")
await this.effects.mount({ location: path, target: options })
} else if (options.type === "backup") {
const subpath = options.subpath
@@ -327,7 +336,7 @@ export class SubContainerOwned<
: "/"
const from = `/media/startos/backup${subpath}`
await bind(from, path, mount.options.filetype)
await bind(from, path, options.filetype, options.idmap)
} else {
throw new Error(`unknown type ${(options as any).type}`)
}
@@ -536,7 +545,9 @@ export class SubContainerOwned<
delete options.cwd
}
if (options?.env) {
for (let [k, v] of Object.entries(options.env)) {
for (let [k, v] of Object.entries(options.env).filter(
([_, v]) => v != undefined,
)) {
extra.push(`--env=${k}=${v}`)
}
}
@@ -585,7 +596,9 @@ export class SubContainerOwned<
delete options.cwd
}
if (options?.env) {
for (let [k, v] of Object.entries(options.env)) {
for (let [k, v] of Object.entries(options.env).filter(
([_, v]) => v != undefined,
)) {
extra.push(`--env=${k}=${v}`)
}
}
@@ -615,9 +628,9 @@ export class SubContainerOwned<
}
export class SubContainerRc<
Manifest extends T.SDKManifest,
Effects extends T.Effects = T.Effects,
>
Manifest extends T.SDKManifest,
Effects extends T.Effects = T.Effects,
>
extends Drop
implements SubContainer<Manifest, Effects>
{
@@ -718,7 +731,9 @@ export class SubContainerRc<
if (rcs < 0) console.error(new Error("UNREACHABLE: rcs < 0").stack)
}
}
await this.destroying
if (this.destroying) {
await this.destroying
}
this.destroyed = true
this.destroying = null
return null
@@ -798,7 +813,7 @@ export type CommandOptions = {
/**
* Environment variables to set for this command
*/
env?: { [variable: string]: string }
env?: { [variable in string]?: string }
/**
* the working directory to run this command in
*/
@@ -813,6 +828,8 @@ export type StdioOptions = {
stdio?: cp.IOType
}
export type IdMap = { fromId: number; toId: number; range: number }
export type MountOptions =
| MountOptionsVolume
| MountOptionsAssets
@@ -825,12 +842,14 @@ export type MountOptionsVolume = {
subpath: string | null
readonly: boolean
filetype: "file" | "directory" | "infer"
idmap: IdMap[]
}
export type MountOptionsAssets = {
type: "assets"
subpath: string | null
filetype: "file" | "directory" | "infer"
idmap: { fromId: number; toId: number; range: number }[]
}
export type MountOptionsPointer = {
@@ -839,13 +858,14 @@ export type MountOptionsPointer = {
volumeId: string
subpath: string | null
readonly: boolean
filetype: "file" | "directory" | "infer"
idmap: { fromId: number; toId: number; range: number }[]
}
export type MountOptionsBackup = {
type: "backup"
subpath: string | null
filetype: "file" | "directory" | "infer"
idmap: { fromId: number; toId: number; range: number }[]
}
function wait(time: number) {
return new Promise((resolve) => setTimeout(resolve, time))