Copy changes for 040 release (#2874)

* update 040 changelog

* remove post_up from 036-alpha6

* backend copy updates

* beta.4

* beta.5

* fix spelling

---------

Co-authored-by: Aiden McClelland <me@drbonez.dev>
This commit is contained in:
Matt Hill
2025-04-21 09:43:35 -06:00
committed by GitHub
parent 2c65033c0a
commit b1621f6b34
12 changed files with 119 additions and 121 deletions

View File

@@ -2,7 +2,6 @@
This guide is for contributing to the StartOS. If you are interested in packaging a service for StartOS, visit the [service packaging guide](https://docs.start9.com/latest/developer-docs/). If you are interested in promoting, providing technical support, creating tutorials, or helping in other ways, please visit the [Start9 website](https://start9.com/contribute).
## Collaboration
- [Matrix](https://matrix.to/#/#community-dev:matrix.start9labs.com)
@@ -13,64 +12,77 @@ This guide is for contributing to the StartOS. If you are interested in packagin
```bash
/
├── assets/
├── container-runtime/
├── core/
├── build/
├── debian/
├── web/
├── image-recipe/
├── patch-db
└── system-images/
└── sdk/
```
#### assets
screenshots for the StartOS README
#### container-runtime
A NodeJS program that dynamically loads maintainer scripts and communicates with the OS to manage packages
#### core
An API, daemon (startd), CLI (start-cli), and SDK (start-sdk) that together provide the core functionality of StartOS.
An API, daemon (startd), and CLI (start-cli) that together provide the core functionality of StartOS.
#### build
Auxiliary files and scripts to include in deployed StartOS images
#### debian
Maintainer scripts for the StartOS Debian package
#### web
Web UIs served under various conditions and used to interact with StartOS APIs.
#### image-recipe
Scripts for building StartOS images
#### patch-db (submodule)
A diff based data store used to synchronize data between the web interfaces and server.
#### system-images
Docker images that assist with creating backups.
#### sdk
A typescript sdk for building start-os packages
## Environment Setup
#### Clone the StartOS repository
```sh
git clone https://github.com/Start9Labs/start-os.git
git clone https://github.com/Start9Labs/start-os.git --recurse-submodules
cd start-os
```
#### Load the PatchDB submodule
```sh
git submodule update --init --recursive
```
#### Continue to your project of interest for additional instructions:
- [`core`](core/README.md)
- [`web-interfaces`](web-interfaces/README.md)
- [`build`](build/README.md)
- [`patch-db`](https://github.com/Start9Labs/patch-db)
## Building
This project uses [GNU Make](https://www.gnu.org/software/make/) to build its components. To build any specific component, simply run `make <TARGET>` replacing `<TARGET>` with the name of the target you'd like to build
### Requirements
- [GNU Make](https://www.gnu.org/software/make/)
- [Docker](https://docs.docker.com/get-docker/)
- [NodeJS v18.15.0](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
- [NodeJS v20.16.0](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
- [sed](https://www.gnu.org/software/sed/)
- [grep](https://www.gnu.org/software/grep/)
- [awk](https://www.gnu.org/software/gawk/)
@@ -79,41 +91,43 @@ This project uses [GNU Make](https://www.gnu.org/software/make/) to build its co
- [brotli](https://github.com/google/brotli)
### Environment variables
- `PLATFORM`: which platform you would like to build for. Must be one of `x86_64`, `x86_64-nonfree`, `aarch64`, `aarch64-nonfree`, `raspberrypi`
- NOTE: `nonfree` images are for including `nonfree` firmware packages in the built ISO
- NOTE: `nonfree` images are for including `nonfree` firmware packages in the built ISO
- `ENVIRONMENT`: a hyphen separated set of feature flags to enable
- `dev`: enables password ssh (INSECURE!) and does not compress frontends
- `unstable`: enables assertions that will cause errors on unexpected inconsistencies that are undesirable in production use either for performance or reliability reasons
- `docker`: use `docker` instead of `podman`
- `dev`: enables password ssh (INSECURE!) and does not compress frontends
- `unstable`: enables assertions that will cause errors on unexpected inconsistencies that are undesirable in production use either for performance or reliability reasons
- `docker`: use `docker` instead of `podman`
- `GIT_BRANCH_AS_HASH`: set to `1` to use the current git branch name as the git hash so that the project does not need to be rebuilt on each commit
### Useful Make Targets
- `iso`: Create a full `.iso` image
- Only possible from Debian
- Not available for `PLATFORM=raspberrypi`
- Additional Requirements:
- [debspawn](https://github.com/lkhq/debspawn)
- Only possible from Debian
- Not available for `PLATFORM=raspberrypi`
- Additional Requirements:
- [debspawn](https://github.com/lkhq/debspawn)
- `img`: Create a full `.img` image
- Only possible from Debian
- Only available for `PLATFORM=raspberrypi`
- Additional Requirements:
- [debspawn](https://github.com/lkhq/debspawn)
- Only possible from Debian
- Only available for `PLATFORM=raspberrypi`
- Additional Requirements:
- [debspawn](https://github.com/lkhq/debspawn)
- `format`: Run automatic code formatting for the project
- Additional Requirements:
- [rust](https://rustup.rs/)
- Additional Requirements:
- [rust](https://rustup.rs/)
- `test`: Run automated tests for the project
- Additional Requirements:
- [rust](https://rustup.rs/)
- Additional Requirements:
- [rust](https://rustup.rs/)
- `update`: Deploy the current working project to a device over ssh as if through an over-the-air update
- Requires an argument `REMOTE` which is the ssh address of the device, i.e. `start9@192.168.122.2`
- Requires an argument `REMOTE` which is the ssh address of the device, i.e. `start9@192.168.122.2`
- `reflash`: Deploy the current working project to a device over ssh as if using a live `iso` image to reflash it
- Requires an argument `REMOTE` which is the ssh address of the device, i.e. `start9@192.168.122.2`
- Requires an argument `REMOTE` which is the ssh address of the device, i.e. `start9@192.168.122.2`
- `update-overlay`: Deploy the current working project to a device over ssh to the in-memory overlay without restarting it
- WARNING: changes will be reverted after the device is rebooted
- WARNING: changes to `init` will not take effect as the device is already initialized
- Requires an argument `REMOTE` which is the ssh address of the device, i.e. `start9@192.168.122.2`
- WARNING: changes will be reverted after the device is rebooted
- WARNING: changes to `init` will not take effect as the device is already initialized
- Requires an argument `REMOTE` which is the ssh address of the device, i.e. `start9@192.168.122.2`
- `wormhole`: Deploy the `startbox` to a device using [magic-wormhole](https://github.com/magic-wormhole/magic-wormhole)
- When the build it complete will emit a command to paste into the shell of the device to upgrade it
- Additional Requirements:
- [magic-wormhole](https://github.com/magic-wormhole/magic-wormhole)
- `clean`: Delete all compiled artifacts
- When the build it complete will emit a command to paste into the shell of the device to upgrade it
- Additional Requirements:
- [magic-wormhole](https://github.com/magic-wormhole/magic-wormhole)
- `clean`: Delete all compiled artifacts

View File

@@ -33,7 +33,7 @@ nvm alias default 20 # this prevents your machine from reverting back to another
## Cloning the repository
```sh
git clone --recursive https://github.com/Start9Labs/start-os.git --branch next/minor
git clone --recursive https://github.com/Start9Labs/start-os.git --branch next/major
cd start-os
```

View File

@@ -73,7 +73,6 @@ export class MainLoop {
env: {
TINI_SUBREAPER: "true",
},
mounts: null,
sigtermTimeout: utils.inMs(
this.system.manifest.main["sigterm-timeout"],
),

View File

@@ -139,7 +139,7 @@ export const polyfillEffects = (
effects,
subcontainer,
[input.command, ...(input.args || [])],
{ mounts: null },
{},
),
)
return {

View File

@@ -1,37 +1,50 @@
# StartOS v0.3.6
# StartOS v0.4.0
## Warning
Previous backups are incompatible with v0.3.6. It is strongly recommended that you (1) immediately update all services, then (2) create a fresh backup. See the [backups](#improved-backups) section below for more details.
Previous backups are incompatible with v0.4.0. It is strongly recommended that you (1) immediately update all services, then (2) create a fresh backup. See the [backups](#improved-backups) section below for more details.
## Summary
Servers are not toys. They are a critical component of the computing paradigm, and their failure can be catastrophic, resulting in downtime or loss of data. From the beginning, Start9 has taken a "security and reliability first" approach to the development of StartOS, favoring soundness over speed and prioritizing essential features such as encrypted network connections, simple backups, and a reliable container runtime over nice-to-haves like custom theming and more apps.
A server is not a toy. It is a critical component of the computing paradigm, and its failure can be catastrophic, resulting in downtime or loss of data. From the beginning, Start9 has taken a "security and reliability first" approach to the development of StartOS, favoring soundness over speed, and prioritizing essential features such as encrypted network connections, simple backups, and a reliable container runtime over nice-to-haves like custom theming and more services.
Start9 is paving new ground with StartOS, trying to achieve what most developers and IT professionals thought impossible; namely, giving a normal person the same independent control over their data and communications as an experienced Linux sysadmin.
Start9 is paving new ground with StartOS, trying to create what most developers and IT professionals thought impossible; namely, an OS and user experience that affords a normal person the same independent control over their data and communications as an experienced Linux sysadmin.
A consequence of our principled approach to development, combined with the difficulty of our endeavor, is that (1) mistakes will be made and (2) they must be corrected. That means a willingness to discard bad ideas and broken parts, and if absolutely necessary, to nuke everything and start over from scratch. We did this in 2020 with StartOS v0.2.0, again in 2022 with StartOS v0.3.0, and now in 2024 with StartOS v0.3.6.
The difficulty of our endeavor requires making mistakes; and our integrity and dedication to excellence require that we correct them. This means a willingness to discard bad ideas and broken parts, and if absolutely necessary, to tear it all down and start over. That is exactly what we did with StartOS v0.2.0 in 2020. It is what we did with StartOS v0.3.0 in 2022. And we are doing it now with StartOS v0.4.0 in 2025.
StartOS v0.3.6 is a complete rewrite of the OS internals (everything you don't see). Almost nothing survived. After nearly five years of building StartOS, we believe that we have finally arrived at the correct architecture and foundation, and that no additional rewrites will be necessary for StartOS to deliver on its promise.
v0.4.0 is a complete rewrite of StartOS, almost nothing survived. After nearly six years of building StartOS, we believe that we have finally arrived at the correct architecture and foundation that will allow us to deliver on the promise of sovereign computing.
## Changelog
- [Improve user interface](#user-interface)
- [Add transaltions](#translations)
- [Switch to lxc-based container runtime](#lxc)
- [Update s9pk archive format](#s9pk-archive-format)
- [Improve Actions](#actions)
- [Use squashfs images for OS updates](#squashfs-updates)
- [Introduce Typescript package API and SDK](#typescript-sdk)
- [Remove Postgresql](#remove-postgressql)
- [Enable sending emails via SMTP](#smtp)
- [Support SSH password auth](#ssh-password-auth)
- [Allow managing Tor addresses](#tor-addresses)
- [Implement detailed progress reporting](#progress-reporting)
- [Improve registry protocol](#registry-protocol)
- [Replace unique .local URLs with unique ports](#lan-port-forwarding)
- [Use start-fs Fuse module for improved backups](#improved-backups)
- [Switch to Exver for versioning](#exver)
- [Support clearnet hosting via start-cli](#clearnet)
- [Add clearnet hosting](#clearnet)
### User interface
We re-wrote the StartOS UI to be more performant, more intuitive, and better looking on both mobile and desktop. Enjoy.
### Translations
StartOS v0.4.0 supports multiple languages and also makes it easy to add more later on.
### LXC
StartOS now uses a nested container paradigm based on LXC for the outer container, and using linux namespaces for the inner lite containers. This replaces both Docker and Podman.
Replacing both Docker and Podman, StartOS v0.4.0 uses a nested container paradigm based on LXC for the outer container and linux namespaces for sub containers. This architecture naturally support multi container setups.
### S9PK archive format
@@ -53,6 +66,18 @@ Package developers can now take advantage of StartOS APIs using the new start-sd
StartOS itself has miniscule data persistence needs. PostgresSQL was overkill and has been removed in favor of lightweight PatchDB.
### SMTP
You can now add your Gmail, SES, or other SMTP credentials to StartOS in order to send deliver email notifications from StartOS and from installed services that support SMTP.
### SSH password auth
You can now SSH into your server using your master password. SSH public key authentication is still supported as well.
### Tor addresses
StartOS v0.4.0 supports adding and removing Tor addresses for StartOS and all service interfaces. You can even provide your own private key instead of using one auto-generated by StartOS. This has the added benefit of permitting vanity addresses.
### Progress reporting
A new progress reporting API enabled package developers to create unique phases and provide real-time progress reporting for actions such as installing, updating, or backing up a service.
@@ -75,10 +100,8 @@ StartOS now uses Extended Versioning (Exver), which consists of three parts: (1)
### Clearnet
It is now possible, and quite easy, to expose service interfaces to the public Internet on a standard domain using start-cli. In addition to choosing which service interfaces to expose on which domains/subdomains, users have two options:
It is now possible (and easy) to expose service interfaces to the public Internet on standard domains. There are two options, both of which are easy to accomplish:
1. Open ports on their router. This option is free and easy to accomplish with most routers. The drawback is that the user's home IP address is revealed to anyone accessing the exposes resources. For example, hosting a blog in this way would reveal your home IP address, and therefor your approximate location on Earth, to your readers.
1. Open ports on your router. This option is free and supported by all routers. The drawback is that your home IP address is revealed to anyone accessing an exposed interface. For example, hosting a blog in this way would reveal your home IP address, and therefore your approximate location, to readers.
2. Use a Wireguard VPN to proxy web traffic. This option requires the user to provision a $5-$10/month remote VPS and perform a few, simple commands. The result is the successful obfuscation of the users home IP address.
The CLI-driven clearnet functionality will be expanded upon and moved into the main StartOS UI in a future release.
2. Use a Wireguard VPN to proxy web traffic. This option requires provisioning a $5-$10/month VPS and running a one-line script. The result is the successful obfuscation of the users home IP address.

View File

@@ -2,7 +2,6 @@ use exver::{PreReleaseSegment, VersionRange};
use super::v0_3_5::V0_3_0_COMPAT;
use super::{v0_3_6_alpha_5, VersionT};
use crate::notifications::{notify, NotificationLevel};
use crate::prelude::*;
lazy_static::lazy_static! {
@@ -30,25 +29,6 @@ impl VersionT for Version {
fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
Ok(())
}
async fn post_up<'a>(self, ctx: &'a crate::context::RpcContext) -> Result<(), Error> {
let message_update = include_str!("update_details/v0_3_6.md").to_string();
ctx.db
.mutate(|db| {
notify(
db,
None,
NotificationLevel::Success,
"Welcome to StartOS 0.3.6!".to_string(),
"Click \"View Details\" to learn all about the new version".to_string(),
message_update,
)?;
Ok(())
})
.await
.result?;
Ok(())
}
fn down(self, _db: &mut Value) -> Result<(), Error> {
Ok(())
}

View File

@@ -3,6 +3,7 @@ use imbl_value::json;
use super::v0_3_5::V0_3_0_COMPAT;
use super::{v0_3_6_alpha_18, VersionT};
use crate::notifications::{notify, NotificationLevel};
use crate::prelude::*;
lazy_static::lazy_static! {
@@ -52,6 +53,25 @@ impl VersionT for Version {
});
Ok(())
}
async fn post_up<'a>(self, ctx: &'a crate::context::RpcContext) -> Result<(), Error> {
let message_update = include_str!("update_details/v0_4_0.md").to_string();
ctx.db
.mutate(|db| {
notify(
db,
None,
NotificationLevel::Success,
"Welcome to StartOS 0.4.0!".to_string(),
"Click \"View Details\" to learn all about the new version".to_string(),
message_update,
)?;
Ok(())
})
.await
.result?;
Ok(())
}
fn down(self, _db: &mut Value) -> Result<(), Error> {
Ok(())
}

View File

@@ -25,18 +25,11 @@ export class CommandController<Manifest extends T.SDKManifest> extends Drop {
static of<Manifest extends T.SDKManifest>() {
return async (
effects: T.Effects,
subcontainer:
| {
imageId: keyof Manifest["images"] & T.ImageId
sharedRun?: boolean
}
| SubContainer<Manifest>,
subcontainer: SubContainer<Manifest>,
command: T.CommandType,
options: {
subcontainerName?: string
// Defaults to the DEFAULT_SIGTERM_TIMEOUT = 30_000ms
sigtermTimeout?: number
mounts: Mounts<Manifest> | null
runAsInit?: boolean
env?:
| {
@@ -60,26 +53,15 @@ export class CommandController<Manifest extends T.SDKManifest> extends Drop {
commands = imageMeta.entrypoint ?? []
commands.concat(...(command.overridCmd ?? imageMeta.cmd ?? []))
} else commands = splitCommand(command)
const subc =
subcontainer instanceof SubContainer
? subcontainer
: await SubContainer.of(
effects,
subcontainer,
null,
options?.subcontainerName || commands.join(" "),
)
try {
if (options.mounts) await subc.mount(options.mounts)
let childProcess: cp.ChildProcess
if (options.runAsInit) {
childProcess = await subc.launch(commands, {
childProcess = await subcontainer.launch(commands, {
env: options.env,
})
} else {
childProcess = await subc.spawn(commands, {
childProcess = await subcontainer.spawn(commands, {
env: options.env,
stdio: options.onStdout || options.onStderr ? "pipe" : "inherit",
})
@@ -116,12 +98,12 @@ export class CommandController<Manifest extends T.SDKManifest> extends Drop {
return new CommandController(
answer,
state,
subc,
subcontainer,
childProcess,
options.sigtermTimeout,
)
} catch (e) {
await subc.destroy()
await subcontainer.destroy()
throw e
}
}

View File

@@ -23,16 +23,9 @@ export class Daemon<Manifest extends T.SDKManifest> {
static of<Manifest extends T.SDKManifest>() {
return async <A extends string>(
effects: T.Effects,
subcontainer:
| {
imageId: keyof Manifest["images"] & T.ImageId
sharedRun?: boolean
}
| SubContainer<Manifest>,
subcontainer: SubContainer<Manifest>,
command: T.CommandType,
options: {
subcontainerName?: string
mounts: Mounts<Manifest> | null
env?:
| {
[variable: string]: string

View File

@@ -57,19 +57,7 @@ type DaemonsParams<
/** The command line command to start the daemon */
command: T.CommandType
/** Information about the subcontainer in which the daemon runs */
subcontainer:
| {
/** The ID of the image. Must be one of the image IDs declared in the manifest */
imageId: keyof Manifest["images"] & T.ImageId
/**
* Whether or not to share the `/run` directory with the parent container.
* This is useful if you are trying to connect to a service that exposes a unix domain socket or auth cookie via the `/run` directory
*/
sharedRun?: boolean
}
| SubContainer<Manifest>
/** For mounting the necessary volumes. Syntax: sdk.Mounts.of().addVolume() */
mounts: Mounts<Manifest>
subcontainer: SubContainer<Manifest>
env?: Record<string, string>
ready: Ready
/** An array of IDs of prior daemons whose successful initializations are required before this daemon will initialize */
@@ -164,7 +152,6 @@ export class Daemons<Manifest extends T.SDKManifest, Ids extends string>
options.command,
{
...options,
subcontainerName: id,
},
)
const healthDaemon = new HealthDaemon(

View File

@@ -1,12 +1,12 @@
{
"name": "@start9labs/start-sdk",
"version": "0.4.0-beta.3",
"version": "0.4.0-beta.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@start9labs/start-sdk",
"version": "0.4.0-beta.3",
"version": "0.4.0-beta.5",
"license": "MIT",
"dependencies": {
"@iarna/toml": "^3.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@start9labs/start-sdk",
"version": "0.4.0-beta.3",
"version": "0.4.0-beta.5",
"description": "Software development kit to facilitate packaging services for StartOS",
"main": "./package/lib/index.js",
"types": "./package/lib/index.d.ts",