From 59550d6f5eba20c14d01cddd61069b31b59d8225 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 18 Mar 2026 13:52:20 -0600 Subject: [PATCH 01/53] dont hide header if table members --- web/projects/start-tunnel/src/styles.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/web/projects/start-tunnel/src/styles.scss b/web/projects/start-tunnel/src/styles.scss index 6829b5003..85cfb90c2 100644 --- a/web/projects/start-tunnel/src/styles.scss +++ b/web/projects/start-tunnel/src/styles.scss @@ -66,10 +66,6 @@ tui-notification-middle { background: var(--tui-background-neutral-1); box-shadow: inset 0 0 0 1px var(--tui-background-neutral-1); - &:has(app-placeholder) thead { - display: none; - } - thead tr { position: sticky; top: 0; From 0e9d4f5d53ae2b80aa7d9acc64a056fa2b339876 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 18 Mar 2026 14:16:18 -0600 Subject: [PATCH 02/53] better wifi page --- .../system/routes/wifi/wifi.component.ts | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts index 6ae42a6b8..0c4ba2174 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts @@ -40,20 +40,21 @@ import { wifiSpec } from './wifi.const' WiFi - @if (status()?.interface) { -
-
- Wi-Fi - - {{ 'Documentation' | i18n }} - +
+
+ Wi-Fi + + {{ 'Documentation' | i18n }} + + + @if (status()?.interface) { -
+ } +
+ + @if (status()?.interface) { @if (status()?.enabled) { @if (wifi(); as data) { @if (data.known.length) { @@ -86,12 +90,12 @@ import { wifiSpec } from './wifi.const' {{ 'WiFi is disabled' | i18n }} } -
- } @else { - - {{ 'No wireless interface detected' | i18n }} - - } + } @else { + + {{ 'No wireless interface detected' | i18n }} + + } + `, styles: ` :host { From 1358937fa9743e7ce80448f389c62d1323ec7b5d Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 18 Mar 2026 15:55:56 -0600 Subject: [PATCH 03/53] fix private domain dns ip and hide private domaains for wg gateways --- .../shared/src/i18n/dictionaries/de.ts | 1 + .../shared/src/i18n/dictionaries/en.ts | 1 + .../shared/src/i18n/dictionaries/es.ts | 1 + .../shared/src/i18n/dictionaries/fr.ts | 3 +- .../shared/src/i18n/dictionaries/pl.ts | 1 + .../addresses/addresses.component.ts | 45 ++++++++++++------- .../addresses/private-dns.component.ts | 9 +++- .../interfaces/interface.service.ts | 2 + 8 files changed, 44 insertions(+), 19 deletions(-) diff --git a/web/projects/shared/src/i18n/dictionaries/de.ts b/web/projects/shared/src/i18n/dictionaries/de.ts index cd5a0de58..3215c61d6 100644 --- a/web/projects/shared/src/i18n/dictionaries/de.ts +++ b/web/projects/shared/src/i18n/dictionaries/de.ts @@ -725,4 +725,5 @@ export default { 802: 'Die Übersetzungen auf Betriebssystemebene sind bereits aktiv. Ein Neustart ist erforderlich, damit die Übersetzungen auf Dienstebene wirksam werden.', 803: 'Dieses Laufwerk verwendet ext4 und wird automatisch in btrfs konvertiert. Ein Backup wird dringend empfohlen, bevor Sie fortfahren.', 804: 'Ich habe ein Backup meiner Daten', + 805: 'Öffentliche Domain hinzufügen', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/en.ts b/web/projects/shared/src/i18n/dictionaries/en.ts index 4310e53a7..957f839df 100644 --- a/web/projects/shared/src/i18n/dictionaries/en.ts +++ b/web/projects/shared/src/i18n/dictionaries/en.ts @@ -726,4 +726,5 @@ export const ENGLISH: Record = { 'OS-level translations are already in effect. A restart is required for service-level translations to take effect.': 802, 'This drive uses ext4 and will be automatically converted to btrfs. A backup is strongly recommended before proceeding.': 803, 'I have a backup of my data': 804, + 'Add Public Domain': 805, } diff --git a/web/projects/shared/src/i18n/dictionaries/es.ts b/web/projects/shared/src/i18n/dictionaries/es.ts index e25fb3f0c..1382c1be5 100644 --- a/web/projects/shared/src/i18n/dictionaries/es.ts +++ b/web/projects/shared/src/i18n/dictionaries/es.ts @@ -725,4 +725,5 @@ export default { 802: 'Las traducciones a nivel del sistema operativo ya están en vigor. Se requiere un reinicio para que las traducciones a nivel de servicio surtan efecto.', 803: 'Esta unidad usa ext4 y se convertirá automáticamente a btrfs. Se recomienda encarecidamente hacer una copia de seguridad antes de continuar.', 804: 'Tengo una copia de seguridad de mis datos', + 805: 'Agregar dominio público', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/fr.ts b/web/projects/shared/src/i18n/dictionaries/fr.ts index c3376b9f4..7fac66a9d 100644 --- a/web/projects/shared/src/i18n/dictionaries/fr.ts +++ b/web/projects/shared/src/i18n/dictionaries/fr.ts @@ -723,6 +723,7 @@ export default { 800: 'Lorsque vous y êtes invité, entrez votre mot de passe StartOS', 801: "Votre système a Secure Boot activé, ce qui exige que tous les modules du noyau soient signés avec une clé de confiance. Certains pilotes matériels \u2014 comme ceux des GPU NVIDIA \u2014 ne sont pas signés par la clé de distribution par défaut. L'enregistrement de la clé de signature StartOS permet à votre firmware de faire confiance à ces modules afin que votre matériel puisse être pleinement utilisé.", 802: "Les traductions au niveau du système d'exploitation sont déjà en vigueur. Un redémarrage est nécessaire pour que les traductions au niveau des services prennent effet.", - 803: "Ce disque utilise ext4 et sera automatiquement converti en btrfs. Il est fortement recommandé de faire une sauvegarde avant de continuer.", + 803: 'Ce disque utilise ext4 et sera automatiquement converti en btrfs. Il est fortement recommandé de faire une sauvegarde avant de continuer.', 804: "J'ai une sauvegarde de mes données", + 805: 'Ajouter un domaine public', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/pl.ts b/web/projects/shared/src/i18n/dictionaries/pl.ts index 770aa4588..2c412f701 100644 --- a/web/projects/shared/src/i18n/dictionaries/pl.ts +++ b/web/projects/shared/src/i18n/dictionaries/pl.ts @@ -725,4 +725,5 @@ export default { 802: 'Tłumaczenia na poziomie systemu operacyjnego są już aktywne. Wymagane jest ponowne uruchomienie, aby tłumaczenia na poziomie usług zaczęły obowiązywać.', 803: 'Ten dysk używa ext4 i zostanie automatycznie skonwertowany na btrfs. Zdecydowanie zaleca się wykonanie kopii zapasowej przed kontynuowaniem.', 804: 'Mam kopię zapasową moich danych', + 805: 'Dodaj domenę publiczną', } satisfies i18n diff --git a/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts b/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts index 96479816a..3a8688556 100644 --- a/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts +++ b/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts @@ -34,23 +34,34 @@ import { InterfaceAddressItemComponent } from './item.component' template: `
{{ 'Gateway' | i18n }}: {{ gatewayGroup().gatewayName }} - - - - + @if (gatewayGroup().isWireguard) { + + } @else { + + + + + }
Date: Wed, 18 Mar 2026 15:59:58 -0600 Subject: [PATCH 05/53] fix: derive wifi interface dynamically from gateway info instead of detecting at startup Remove static wifi_interface/ethernet_interface fields from RpcContextSeed. Instead, look up the wifi interface from the DB (populated by gateway sync) and check ethernet connectivity by querying gateway entries. This ensures the wifi manager always uses the correct interface even if network devices change after boot. --- core/src/context/rpc.rs | 11 +- core/src/db/model/public.rs | 4 +- core/src/init.rs | 26 ++--- core/src/net/gateway.rs | 35 ++++-- core/src/net/wifi.rs | 227 +++++++++++++++++++----------------- 5 files changed, 164 insertions(+), 139 deletions(-) diff --git a/core/src/context/rpc.rs b/core/src/context/rpc.rs index 204b000b5..dbb886f3c 100644 --- a/core/src/context/rpc.rs +++ b/core/src/context/rpc.rs @@ -35,7 +35,6 @@ use crate::lxc::LxcManager; use crate::net::gateway::WildcardListener; use crate::net::net_controller::{NetController, NetService}; use crate::net::socks::DEFAULT_SOCKS_LISTEN; -use crate::net::utils::{find_eth_iface, find_wifi_iface}; use crate::net::web_server::WebServerAcceptorSetter; use crate::net::wifi::WpaCli; use crate::prelude::*; @@ -55,8 +54,6 @@ use crate::{DATA_DIR, PLATFORM, PackageId}; pub struct RpcContextSeed { is_closed: AtomicBool, pub os_partitions: OsPartitionInfo, - pub wifi_interface: Option, - pub ethernet_interface: String, pub disk_guid: InternedString, pub ephemeral_sessions: SyncMutex, pub db: TypedPatchDb, @@ -73,7 +70,7 @@ pub struct RpcContextSeed { pub open_authed_continuations: OpenAuthedContinuations>, pub rpc_continuations: RpcContinuations, pub callbacks: Arc, - pub wifi_manager: Arc>>, + pub wifi_manager: RwLock>, pub current_secret: Arc, pub client: Client, pub start_time: Instant, @@ -323,13 +320,9 @@ impl RpcContext { }); } - let wifi_interface = find_wifi_iface().await?; - let seed = Arc::new(RpcContextSeed { is_closed: AtomicBool::new(false), os_partitions: OsPartitionInfo::from_fstab().await?, - wifi_interface: wifi_interface.clone(), - ethernet_interface: find_eth_iface().await?, disk_guid, ephemeral_sessions: SyncMutex::new(Sessions::new()), sync_db: watch::Sender::new(db.sequence().await), @@ -350,7 +343,7 @@ impl RpcContext { shutdown, lxc_manager: Arc::new(LxcManager::new()), open_authed_continuations: OpenAuthedContinuations::new(), - wifi_manager: Arc::new(RwLock::new(wifi_interface.clone().map(|i| WpaCli::init(i)))), + wifi_manager: RwLock::new(None), current_secret: Arc::new( Jwk::generate_ec_key(josekit::jwk::alg::ec::EcCurve::P256).map_err(|e| { tracing::debug!("{:?}", e); diff --git a/core/src/db/model/public.rs b/core/src/db/model/public.rs index 9477dac82..11b68c226 100644 --- a/core/src/db/model/public.rs +++ b/core/src/db/model/public.rs @@ -98,7 +98,7 @@ impl Public { port_forwards: BTreeSet::new(), }, wifi: WifiInfo { - enabled: true, + enabled: false, ..Default::default() }, gateways: OrdMap::new(), @@ -378,7 +378,7 @@ pub struct ServerStatus { #[ts(export)] pub struct WifiInfo { pub enabled: bool, - pub interface: Option, + pub interface: Option, pub ssids: BTreeSet, pub selected: Option, #[ts(type = "string | null")] diff --git a/core/src/init.rs b/core/src/init.rs index ce489c0e9..eb74d6a19 100644 --- a/core/src/init.rs +++ b/core/src/init.rs @@ -23,7 +23,6 @@ use crate::middleware::auth::local::LocalAuthContext; use crate::net::gateway::WildcardListener; use crate::net::net_controller::{NetController, NetService}; use crate::net::socks::DEFAULT_SOCKS_LISTEN; -use crate::net::utils::find_wifi_iface; use crate::net::web_server::WebServerAcceptorSetter; use crate::prelude::*; use crate::progress::{ @@ -280,20 +279,17 @@ pub async fn init( load_ca_cert.complete(); load_wifi.start(); - let wifi_interface = find_wifi_iface().await?; - let wifi = db - .mutate(|db| { - let wifi = db - .as_public_mut() - .as_server_info_mut() - .as_network_mut() - .as_wifi_mut(); - wifi.as_interface_mut().ser(&wifi_interface)?; - wifi.de() - }) - .await - .result?; - crate::net::wifi::synchronize_network_manager(MAIN_DATA, &wifi).await?; + crate::net::wifi::synchronize_network_manager( + MAIN_DATA, + &peek + .as_public() + .as_server_info() + .as_network() + .as_wifi() + .de() + .unwrap_or_default(), + ) + .await?; load_wifi.complete(); init_tmp.start(); diff --git a/core/src/net/gateway.rs b/core/src/net/gateway.rs index 91a012df1..a4959b796 100644 --- a/core/src/net/gateway.rs +++ b/core/src/net/gateway.rs @@ -34,6 +34,7 @@ use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceTyp use crate::net::forward::START9_BRIDGE_IFACE; use crate::net::gateway::device::DeviceProxy; use crate::net::host::all_hosts; +use crate::net::utils::find_wifi_iface; use crate::net::web_server::{Accept, AcceptStream, MetadataVisitor, TcpMetadata}; use crate::prelude::*; use crate::util::Invoke; @@ -775,7 +776,9 @@ async fn watcher( async fn get_wan_ipv4(iface: &str, base_url: &Url) -> Result, Error> { let client = reqwest::Client::builder(); #[cfg(target_os = "linux")] - let client = client.interface(iface); + let client = client + .interface(iface) + .local_address(IpAddr::V4(Ipv4Addr::UNSPECIFIED)); let url = base_url.join("/ip").with_kind(ErrorKind::ParseUrl)?; let text = client .build()? @@ -1289,14 +1292,15 @@ async fn poll_ip_info( }; let mut wan_ip = None; for echoip_url in echoip_urls { - let wan_ip = if echoip_ratelimit_state + if echoip_ratelimit_state .get(&echoip_url) .map_or(true, |i| i.elapsed() > Duration::from_secs(300)) && !subnets.is_empty() && !matches!( device_type, Some(NetworkInterfaceType::Bridge | NetworkInterfaceType::Loopback) - ) { + ) + { match get_wan_ipv4(iface.as_str(), &echoip_url).await { Ok(a) => { wan_ip = a; @@ -1458,12 +1462,27 @@ impl NetworkInterfaceController { ) -> Result<(), Error> { tracing::debug!("syncronizing {info:?} to db"); + let mut wifi_iface = info + .iter() + .find(|(_, info)| { + info.ip_info.as_ref().map_or(false, |i| { + i.device_type == Some(NetworkInterfaceType::Wireless) + }) + }) + .map(|(id, _)| id.clone()); + if wifi_iface.is_none() { + wifi_iface = find_wifi_iface() + .await + .ok() + .and_then(|a| a) + .map(InternedString::from) + .map(GatewayId::from); + } + db.mutate(|db| { - db.as_public_mut() - .as_server_info_mut() - .as_network_mut() - .as_gateways_mut() - .ser(info)?; + let network = db.as_public_mut().as_server_info_mut().as_network_mut(); + network.as_gateways_mut().ser(info)?; + network.as_wifi_mut().as_interface_mut().ser(&wifi_iface)?; let hostname = crate::hostname::ServerHostname::load(db.as_public().as_server_info())?; let ports = db.as_private().as_available_ports().de()?; for host in all_hosts(db) { diff --git a/core/src/net/wifi.rs b/core/src/net/wifi.rs index 57ccbd107..cead621bb 100644 --- a/core/src/net/wifi.rs +++ b/core/src/net/wifi.rs @@ -1,6 +1,5 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::path::Path; -use std::sync::Arc; use std::time::Duration; use clap::Parser; @@ -11,30 +10,100 @@ use regex::Regex; use rpc_toolkit::{Context, Empty, HandlerExt, ParentHandler, from_fn_async}; use serde::{Deserialize, Serialize}; use tokio::process::Command; -use tokio::sync::RwLock; +use tokio::sync::{RwLockMappedWriteGuard, RwLockReadGuard, RwLockWriteGuard}; use tracing::instrument; use ts_rs::TS; use crate::context::{CliContext, RpcContext}; use crate::db::model::Database; -use crate::db::model::public::WifiInfo; +use crate::db::model::public::{NetworkInterfaceType, WifiInfo}; use crate::prelude::*; use crate::util::Invoke; use crate::util::serde::{HandlerExtSerde, WithIoFormat, display_serializable}; -use crate::{Error, ErrorKind}; +use crate::{Error, ErrorKind, GatewayId}; -type WifiManager = Arc>>; +impl RpcContext { + async fn read_wifi_manager(&self) -> Result, Error> { + let err = || { + Error::new( + color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), + ErrorKind::Wifi, + ) + }; + let Some(interface) = self + .db + .peek() + .await + .as_public() + .as_server_info() + .as_network() + .as_wifi() + .as_interface() + .de()? + else { + return Err(err()); + }; + let mut cli = RwLockReadGuard::try_map(self.wifi_manager.read().await, |c| c.as_ref()).ok(); + while cli.as_ref().map_or(true, |c| c.interface != interface) { + drop(cli.take()); + let mut guard = self.wifi_manager.write().await; + *guard = Some(WpaCli::new(interface.clone())); + drop(guard); + cli = RwLockReadGuard::try_map(self.wifi_manager.read().await, |c| c.as_ref()).ok(); + } + cli.ok_or_else(err) + } -// pub fn wifi_manager(ctx: &RpcContext) -> Result<&WifiManager, Error> { -// if let Some(wifi_manager) = ctx.wifi_manager.as_ref() { -// Ok(wifi_manager) -// } else { -// Err(Error::new( -// color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), -// ErrorKind::Wifi, -// )) -// } -// } + async fn write_wifi_manager(&self) -> Result, Error> { + let err = || { + Error::new( + color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), + ErrorKind::Wifi, + ) + }; + let Some(interface) = self + .db + .peek() + .await + .as_public() + .as_server_info() + .as_network() + .as_wifi() + .as_interface() + .de()? + else { + return Err(err()); + }; + let mut cli = self.wifi_manager.write().await; + if cli.as_ref().map_or(true, |c| c.interface != interface) { + *cli = Some(WpaCli::new(interface)); + } + RwLockWriteGuard::try_map(cli, |c| c.as_mut()).map_err(|_| err()) + } + + async fn ethernet_interface_connected(&self) -> Result { + for (iface, info) in self + .db + .peek() + .await + .as_public() + .as_server_info() + .as_network() + .as_gateways() + .as_entries()? + { + let Some(info) = info.as_ip_info().transpose_ref() else { + continue; + }; + if info.as_deref().as_device_type().de()? == Some(NetworkInterfaceType::Ethernet) { + if interface_connected(iface.as_str()).await? { + return Ok(true); + } + } + } + Ok(false) + } +} pub fn wifi() -> ParentHandler { ParentHandler::new() @@ -165,55 +234,35 @@ pub async fn add( ctx: RpcContext, WifiAddParams { ssid, password }: WifiAddParams, ) -> Result<(), Error> { - let wifi_manager = ctx.wifi_manager.clone(); + let mut wpa_supplicant = ctx.write_wifi_manager().await?; if !ssid.is_ascii() { return Err(Error::new( color_eyre::eyre::eyre!("{}", t!("net.wifi.ssid-no-special-characters")), ErrorKind::Wifi, )); } + let ssid = Ssid(ssid); if !password.is_ascii() { return Err(Error::new( color_eyre::eyre::eyre!("{}", t!("net.wifi.password-no-special-characters")), ErrorKind::Wifi, )); } - async fn add_procedure( - db: TypedPatchDb, - wifi_manager: WifiManager, - ssid: &Ssid, - password: &Psk, - ) -> Result<(), Error> { - tracing::info!("{}", t!("net.wifi.adding-network", ssid = &ssid.0)); - let mut wpa_supplicant = wifi_manager.write_owned().await; - let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| { - Error::new( - color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), - ErrorKind::Wifi, - ) - })?; - wpa_supplicant.add_network(db, ssid, password).await?; - Ok(()) - } - if let Err(err) = add_procedure( - ctx.db.clone(), - wifi_manager.clone(), - &Ssid(ssid.clone()), - &Psk(password.clone()), - ) - .await + if let Err(err) = wpa_supplicant + .add_network(ctx.db.clone(), &ssid, &Psk(password)) + .await { tracing::error!( "{}", t!( "net.wifi.failed-to-add-network", - ssid = &ssid, + ssid = &ssid.0, error = err.to_string() ) ); tracing::debug!("{:?}", err); return Err(Error::new( - color_eyre::eyre::eyre!("{}", t!("net.wifi.failed-adding", ssid = &ssid)), + color_eyre::eyre::eyre!("{}", t!("net.wifi.failed-adding", ssid = &ssid.0)), ErrorKind::Wifi, )); } @@ -225,7 +274,7 @@ pub async fn add( .as_wifi_mut() .as_ssids_mut() .mutate(|s| { - s.insert(ssid); + s.insert(ssid.0); Ok(()) }) }) @@ -247,45 +296,36 @@ pub async fn connect( ctx: RpcContext, WifiSsidParams { ssid }: WifiSsidParams, ) -> Result<(), Error> { - let wifi_manager = ctx.wifi_manager.clone(); + let mut wpa_supplicant = ctx.write_wifi_manager().await?; if !ssid.is_ascii() { return Err(Error::new( color_eyre::eyre::eyre!("{}", t!("net.wifi.ssid-no-special-characters")), ErrorKind::Wifi, )); } - async fn connect_procedure( - db: TypedPatchDb, - wifi_manager: WifiManager, - ssid: &Ssid, - ) -> Result<(), Error> { - let mut wpa_supplicant = wifi_manager.write_owned().await; - let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| { - Error::new( - color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), - ErrorKind::Wifi, - ) - })?; + if let Err(err) = async { let current = wpa_supplicant.get_current_network().await?; - let connected = wpa_supplicant.select_network(db.clone(), ssid).await?; + let connected = wpa_supplicant + .select_network(ctx.db.clone(), &Ssid(ssid.clone())) + .await?; if connected { - tracing::info!("{}", t!("net.wifi.connected-successfully", ssid = &ssid.0)); + tracing::info!("{}", t!("net.wifi.connected-successfully", ssid = &ssid)); } else { - tracing::info!("{}", t!("net.wifi.connection-failed", ssid = &ssid.0)); + tracing::info!("{}", t!("net.wifi.connection-failed", ssid = &ssid)); match current { None => { tracing::info!("{}", t!("net.wifi.no-wifi-to-revert")); } Some(current) => { - wpa_supplicant.select_network(db, ¤t).await?; + wpa_supplicant + .select_network(ctx.db.clone(), ¤t) + .await?; } } } - Ok(()) + Ok::<_, Error>(()) } - - if let Err(err) = - connect_procedure(ctx.db.clone(), wifi_manager.clone(), &Ssid(ssid.clone())).await + .await { tracing::error!( "{}", @@ -321,26 +361,18 @@ pub async fn connect( #[instrument(skip_all)] pub async fn remove(ctx: RpcContext, WifiSsidParams { ssid }: WifiSsidParams) -> Result<(), Error> { - let wifi_manager = ctx.wifi_manager.clone(); + let mut wpa_supplicant = ctx.write_wifi_manager().await?; if !ssid.is_ascii() { return Err(Error::new( color_eyre::eyre::eyre!("{}", t!("net.wifi.ssid-no-special-characters")), ErrorKind::Wifi, )); } - - let mut wpa_supplicant = wifi_manager.write_owned().await; - let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| { - Error::new( - color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), - ErrorKind::Wifi, - ) - })?; let current = wpa_supplicant.get_current_network().await?; let ssid = Ssid(ssid); let is_current_being_removed = matches!(current, Some(current) if current == ssid); let is_current_removed_and_no_hardwire = - is_current_being_removed && !interface_connected(&ctx.ethernet_interface).await?; + is_current_being_removed && !ctx.ethernet_interface_connected().await?; if is_current_removed_and_no_hardwire { return Err(Error::new( color_eyre::eyre::eyre!("{}", t!("net.wifi.forbidden-delete-would-disconnect")), @@ -487,19 +519,12 @@ fn display_wifi_list(params: WithIoFormat, info: Vec) -> Res // #[command(display(display_wifi_info))] #[instrument(skip_all)] pub async fn get(ctx: RpcContext, _: Empty) -> Result { - let wifi_manager = ctx.wifi_manager.clone(); - let wpa_supplicant = wifi_manager.read_owned().await; - let wpa_supplicant = wpa_supplicant.as_ref().ok_or_else(|| { - Error::new( - color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), - ErrorKind::Wifi, - ) - })?; + let wpa_supplicant = ctx.read_wifi_manager().await?; let (list_networks, current_res, country_res, ethernet_res, signal_strengths) = tokio::join!( wpa_supplicant.list_networks_low(), wpa_supplicant.get_current_network(), wpa_supplicant.get_country_low(), - interface_connected(&ctx.ethernet_interface), + ctx.ethernet_interface_connected(), wpa_supplicant.list_wifi_low() ); let signal_strengths = signal_strengths?; @@ -541,14 +566,7 @@ pub async fn get(ctx: RpcContext, _: Empty) -> Result { #[instrument(skip_all)] pub async fn get_available(ctx: RpcContext, _: Empty) -> Result, Error> { - let wifi_manager = ctx.wifi_manager.clone(); - let wpa_supplicant = wifi_manager.read_owned().await; - let wpa_supplicant = wpa_supplicant.as_ref().ok_or_else(|| { - Error::new( - color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), - ErrorKind::Wifi, - ) - })?; + let wpa_supplicant = ctx.read_wifi_manager().await?; let (wifi_list, network_list) = tokio::join!( wpa_supplicant.list_wifi_low(), wpa_supplicant.list_networks_low() @@ -584,20 +602,13 @@ pub async fn set_country( ctx: RpcContext, SetCountryParams { country }: SetCountryParams, ) -> Result<(), Error> { - let wifi_manager = ctx.wifi_manager.clone(); - if !interface_connected(&ctx.ethernet_interface).await? { + if !ctx.ethernet_interface_connected().await? { return Err(Error::new( color_eyre::eyre::eyre!("{}", t!("net.wifi.wont-change-country-without-ethernet")), crate::ErrorKind::Wifi, )); } - let mut wpa_supplicant = wifi_manager.write_owned().await; - let wpa_supplicant = wpa_supplicant.as_mut().ok_or_else(|| { - Error::new( - color_eyre::eyre::eyre!("{}", t!("net.wifi.no-interface-available")), - ErrorKind::Wifi, - ) - })?; + let mut wpa_supplicant = ctx.write_wifi_manager().await?; wpa_supplicant.set_country_low(country.alpha2()).await?; for (network_id, _wifi_info) in wpa_supplicant.list_networks_low().await? { wpa_supplicant.remove_network_low(network_id).await?; @@ -611,7 +622,7 @@ pub async fn set_country( #[derive(Debug)] pub struct WpaCli { - interface: String, + interface: GatewayId, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct NetworkId(String); @@ -661,7 +672,7 @@ pub struct WifiInfoLow { #[derive(Clone, Debug)] pub struct Psk(String); impl WpaCli { - pub fn init(interface: String) -> Self { + pub fn new(interface: GatewayId) -> Self { WpaCli { interface } } @@ -709,7 +720,7 @@ impl WpaCli { .arg("modify") .arg(&ssid.0) .arg("ifname") - .arg(&self.interface) + .arg(self.interface.as_str()) .invoke(ErrorKind::Wifi) .await .map(|_| ()) @@ -951,7 +962,7 @@ impl WpaCli { #[instrument(skip_all)] pub async fn get_current_network(&self) -> Result, Error> { let r = Command::new("iwgetid") - .arg(&self.interface) + .arg(self.interface.as_str()) .arg("--raw") .invoke(ErrorKind::Wifi) .await?; @@ -1055,6 +1066,12 @@ pub async fn synchronize_network_manager>( .arg("all") .invoke(ErrorKind::Wifi) .await?; + } else { + Command::new("rfkill") + .arg("unblock") + .arg("all") + .invoke(ErrorKind::Wifi) + .await?; } Command::new("ip") @@ -1093,7 +1110,7 @@ pub async fn synchronize_network_manager>( }; Command::new("ifconfig") - .arg(wifi_iface) + .arg(wifi_iface.as_str()) .arg("up") .invoke(ErrorKind::Wifi) .await?; From 6e56682c11888a446c779d75462b0776d2ff95bd Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 18 Mar 2026 16:52:47 -0600 Subject: [PATCH 06/53] better wifi ux --- .../system/routes/wifi/wifi.component.ts | 63 +++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts index 0c4ba2174..24b6075eb 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/wifi/wifi.component.ts @@ -3,6 +3,7 @@ import { ChangeDetectorRef, Component, inject, + signal, } from '@angular/core' import { toSignal } from '@angular/core/rxjs-interop' import { FormsModule } from '@angular/forms' @@ -15,10 +16,26 @@ import { pauseFor, } from '@start9labs/shared' import { TuiButton, TuiLoader, TuiNotificationService } from '@taiga-ui/core' -import { TuiNotificationMiddleService, TuiSwitch } from '@taiga-ui/kit' +import { + TuiButtonLoading, + TuiNotificationMiddleService, + TuiSwitch, +} from '@taiga-ui/kit' import { TuiCardLarge } from '@taiga-ui/layout' import { PatchDB } from 'patch-db-client' -import { catchError, defer, map, merge, Observable, of, Subject } from 'rxjs' +import { + catchError, + defer, + finalize, + first, + map, + merge, + Observable, + of, + Subject, + switchMap, + tap, +} from 'rxjs' import { FormComponent, FormContext, @@ -55,10 +72,23 @@ import { wifiSpec } from './wifi.const' @if (status()?.interface) { + @if (status()?.enabled) { + + } () + private readonly refresh$ = new Subject() private readonly formDialog = inject(FormDialogService) private readonly cdr = inject(ChangeDetectorRef) private readonly patch = inject>(PatchDB) private readonly i18n = inject(i18nPipe) - readonly status = toSignal(this.patch.watch$('serverInfo', 'network', 'wifi')) - readonly wifi = toSignal(merge(this.getWifi$(), this.update$)) + private readonly status$ = this.patch.watch$('serverInfo', 'network', 'wifi') + readonly status = toSignal(this.status$) + readonly wifi = toSignal( + merge( + this.status$.pipe( + first(s => !!s?.interface), + switchMap(() => this.getWifi$()), + ), + this.refresh$.pipe( + tap(() => this.refreshing.set(true)), + switchMap(() => + this.getWifi$().pipe(finalize(() => this.refreshing.set(false))), + ), + ), + this.update$, + ), + ) + + readonly refreshing = signal(false) + + refresh() { + this.refresh$.next() + } async onToggle(enable: boolean) { const loader = this.loader From 476b10c413721724de4d41103083adf633f3b2cd Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Wed, 18 Mar 2026 23:47:05 -0600 Subject: [PATCH 07/53] chore: update dependencies and build scripts --- build/apt/publish-deb.sh | 3 +- build/download-tor-s9pk.sh | 3 +- container-runtime/package-lock.json | 1 + core/Cargo.lock | 712 ++++++++++++++-------------- core/Cargo.toml | 11 +- core/run-tests.sh | 2 +- 6 files changed, 381 insertions(+), 351 deletions(-) diff --git a/build/apt/publish-deb.sh b/build/apt/publish-deb.sh index b049e2796..9231d6964 100755 --- a/build/apt/publish-deb.sh +++ b/build/apt/publish-deb.sh @@ -23,6 +23,7 @@ fi BUCKET="${S3_BUCKET:-start9-debs}" ENDPOINT="${S3_ENDPOINT:-https://nyc3.digitaloceanspaces.com}" +GPG_KEY_ID="${GPG_KEY_ID:-5259ADFC2D63C217}" SUITE="${SUITE:-stable}" COMPONENT="${COMPONENT:-main}" REPO_DIR="$(mktemp -d)" @@ -98,7 +99,7 @@ for arch in amd64 arm64 riscv64; do mkdir -p "$BINARY_DIR" ( cd "$REPO_DIR" - dpkg-scanpackages --arch "$arch" pool/ > "$BINARY_DIR/Packages" + dpkg-scanpackages --multiversion --arch "$arch" pool/ > "$BINARY_DIR/Packages" gzip -k -f "$BINARY_DIR/Packages" ) echo "Generated Packages index for ${arch}" diff --git a/build/download-tor-s9pk.sh b/build/download-tor-s9pk.sh index 8feb9f597..6a37c82a2 100755 --- a/build/download-tor-s9pk.sh +++ b/build/download-tor-s9pk.sh @@ -5,10 +5,11 @@ cd "$(dirname "${BASH_SOURCE[0]}")" set -e ARCH=$1 +VERSION="0.4.9.5:0-beta.0" if [ -z "$ARCH" ]; then >&2 echo "usage: $0 " exit 1 fi -curl --fail -L -o "./lib/tor_${ARCH}.s9pk" "https://s9pks.nyc3.cdn.digitaloceanspaces.com/tor_${ARCH}.s9pk" +curl --fail -L -o "./lib/tor_${ARCH}.s9pk" "https://s9pks.nyc3.cdn.digitaloceanspaces.com/tor/${VERSION}/tor_${ARCH}.s9pk" diff --git a/container-runtime/package-lock.json b/container-runtime/package-lock.json index ff2e560de..e47b4d89a 100644 --- a/container-runtime/package-lock.json +++ b/container-runtime/package-lock.json @@ -45,6 +45,7 @@ "@noble/hashes": "^1.7.2", "@types/ini": "^4.1.1", "deep-equality-data-structures": "^2.0.0", + "fast-xml-parser": "^5.5.6", "ini": "^5.0.0", "isomorphic-fetch": "^3.0.0", "mime": "^4.0.7", diff --git a/core/Cargo.lock b/core/Cargo.lock index 8bb465168..43b086318 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -103,9 +103,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -118,15 +118,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -153,9 +153,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "ar_archive_writer" @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ded5f9a03ac8f24d1b8a25101ee812cd32cdc8c50a4c50237de2c4915850e73" +checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" dependencies = [ "rustversion", ] @@ -232,7 +232,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "synstructure", ] @@ -244,7 +244,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -260,7 +260,7 @@ dependencies = [ "pem", "rcgen", "ring", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pemfile", "serde", "serde_json", @@ -306,9 +306,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68650b7df54f0293fd061972a0fb05aaf4fc0879d3b3d21a638a182c5c543b9f" +checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1" dependencies = [ "compression-codecs", "compression-core", @@ -318,9 +318,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", @@ -343,7 +343,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.3", + "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] @@ -374,7 +374,7 @@ dependencies = [ "cfg-if", "event-listener 5.4.1", "futures-lite", - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -385,7 +385,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -400,7 +400,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.1.3", + "rustix 1.1.4", "signal-hook-registry", "slab", "windows-sys 0.61.2", @@ -425,7 +425,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -442,7 +442,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -468,9 +468,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.15.4" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" +checksum = "94bffc006df10ac2a68c83692d734a465f8ee6c5b384d8545a636f81d858f4bf" dependencies = [ "aws-lc-sys", "zeroize", @@ -478,9 +478,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.37.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" +checksum = "4321e568ed89bb5a7d291a7f37997c2c0df89809d7b6d12062c81ddb54aa782e" dependencies = [ "cc", "cmake", @@ -592,9 +592,9 @@ checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" [[package]] name = "base62" -version = "2.2.3" +version = "2.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adf9755786e27479693dedd3271691a92b5e242ab139cacb9fb8e7fb5381111" +checksum = "cd637ac531c60eb7fbc4684dc061c2d7d90d73d758181aa02eeff0464b9eee4b" [[package]] name = "base64" @@ -692,9 +692,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bitmaps" @@ -749,7 +749,7 @@ dependencies = [ "cfg-if", "constant_time_eq", "cpufeatures", - "memmap2 0.9.9", + "memmap2 0.9.10", "rayon-core", ] @@ -823,9 +823,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytemuck" @@ -853,9 +853,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cc" -version = "1.2.55" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ "find-msvc-tools", "jobserver", @@ -889,9 +889,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -959,9 +959,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.58" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -969,9 +969,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.58" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -982,21 +982,31 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "clap_mangen" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30ffc187e2e3aeafcd1c6e2aa416e29739454c0ccaa419226d5ecd181f2d78" +dependencies = [ + "clap", + "roff", +] [[package]] name = "clipboard-win" @@ -1046,9 +1056,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "colorgrad" @@ -1071,9 +1081,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" +checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7" dependencies = [ "brotli", "compression-core", @@ -1100,13 +1110,12 @@ dependencies = [ [[package]] name = "console" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4" +checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" dependencies = [ "encode_unicode", "libc", - "once_cell", "unicode-width 0.2.2", "windows-sys 0.61.2", ] @@ -1214,9 +1223,9 @@ dependencies = [ [[package]] name = "cookie_store" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc4bff745c9b4c7fb1e97b25d13153da2bc7796260141df62378998d070207f" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" dependencies = [ "cookie", "document-features", @@ -1370,14 +1379,14 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "crossterm_winapi", "derive_more", "document-features", "futures-core", "mio", "parking_lot 0.12.5", - "rustix 1.1.3", + "rustix 1.1.4", "signal-hook", "signal-hook-mio", "winapi", @@ -1496,7 +1505,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -1539,14 +1548,14 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] name = "deranged" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -1570,7 +1579,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -1629,7 +1638,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -1640,9 +1649,9 @@ checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82" [[package]] name = "dlib" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ "libloading", ] @@ -1655,7 +1664,7 @@ checksum = "6e39034cee21a2f5bbb66ba0e3689819c4bb5d00382a282006e802a7ffa6c41d" dependencies = [ "cfg-if", "libc", - "socket2 0.6.2", + "socket2 0.6.3", "windows-sys 0.60.2", ] @@ -1852,7 +1861,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -1873,7 +1882,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -2114,9 +2123,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -2129,9 +2138,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -2139,15 +2148,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -2167,9 +2176,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -2186,13 +2195,13 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -2208,21 +2217,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -2232,7 +2241,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -2318,20 +2326,20 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "wasip2", "wasip3", ] @@ -2358,7 +2366,7 @@ dependencies = [ "bstr", "log", "regex-automata 0.4.14", - "regex-syntax 0.8.9", + "regex-syntax 0.8.10", ] [[package]] @@ -2378,7 +2386,7 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3696fafb1ecdcc2ae3ce337de73e9202806068594b77d22fdf2f3573c5ec2219" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "crc", "simple-bytes", "uuid", @@ -2731,7 +2739,7 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", @@ -2785,7 +2793,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.2", + "socket2 0.6.3", "system-configuration", "tokio", "tower-service", @@ -2965,9 +2973,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.9" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", @@ -3072,9 +3080,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.3" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88" +checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ "console", "portable-atomic", @@ -3086,11 +3094,11 @@ dependencies = [ [[package]] name = "inotify" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "futures-core", "inotify-sys", "libc", @@ -3148,9 +3156,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" dependencies = [ "serde", ] @@ -3338,9 +3346,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -3414,7 +3422,7 @@ dependencies = [ "petgraph", "pico-args", "regex", - "regex-syntax 0.8.9", + "regex-syntax 0.8.10", "string_cache", "term", "tiny-keccak", @@ -3489,9 +3497,9 @@ dependencies = [ "nom 8.0.0", "percent-encoding", "quoted_printable", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-platform-verifier", - "socket2 0.6.2", + "socket2 0.6.3", "tokio", "tokio-rustls 0.26.4", "url", @@ -3512,9 +3520,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.181" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libloading" @@ -3544,13 +3552,14 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "redox_syscall 0.7.1", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -3577,9 +3586,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -3678,9 +3687,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", ] @@ -3730,7 +3739,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -3778,9 +3787,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.13" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" +checksum = "85f8024e1c8e71c778968af91d43700ce1d11b219d127d79fb2934153b82b42b" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -3795,9 +3804,9 @@ dependencies = [ [[package]] name = "moxcms" -version = "0.7.11" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" dependencies = [ "num-traits", "pxfm", @@ -3805,17 +3814,17 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cdede44f9a69cab2899a2049e2c3bd49bf911a157f6a3353d4a91c61abbce44" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", "openssl", - "openssl-probe 0.1.6", + "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -3867,7 +3876,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases 0.1.1", "libc", @@ -3879,7 +3888,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases 0.2.1", "libc", @@ -4045,9 +4054,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -4055,14 +4064,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -4120,9 +4129,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", @@ -4140,7 +4149,7 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", "once_cell", "onig_sys", @@ -4177,11 +4186,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "foreign-types", "libc", @@ -4198,15 +4207,9 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "openssl-probe" version = "0.2.1" @@ -4224,9 +4227,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", @@ -4253,9 +4256,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "4.2.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" [[package]] name = "p256" @@ -4455,7 +4458,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -4508,7 +4511,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -4528,29 +4531,29 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -4560,9 +4563,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -4596,6 +4599,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "plist" version = "1.8.0" @@ -4619,7 +4628,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -4707,7 +4716,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -4735,11 +4744,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit 0.25.5+spec-1.1.0", ] [[package]] @@ -4757,11 +4766,11 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "chrono", "flate2", "procfs-core", - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -4770,7 +4779,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "chrono", "hex", ] @@ -4783,12 +4792,12 @@ checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.10.0", + "bitflags 2.11.0", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", "rand_xorshift", - "regex-syntax 0.8.9", + "regex-syntax 0.8.10", "rusty-fork", "tempfile", "unarray", @@ -4802,7 +4811,7 @@ checksum = "fb6dc647500e84a25a85b100e76c85b8ace114c209432dc174f20aac11d4ed6c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -4825,7 +4834,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -4859,7 +4868,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71cec9e2670207c5ebb9e477763c74436af3b9091dd550b9fb3c1bec7f3ea266" dependencies = [ - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -4874,12 +4883,9 @@ dependencies = [ [[package]] name = "pxfm" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" -dependencies = [ - "num-traits", -] +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" [[package]] name = "qrcode" @@ -4917,8 +4923,8 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.36", - "socket2 0.6.2", + "rustls 0.23.37", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -4927,9 +4933,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "bytes", "getrandom 0.3.4", @@ -4937,7 +4943,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -4955,16 +4961,16 @@ dependencies = [ "cfg_aliases 0.2.1", "libc", "once_cell", - "socket2 0.6.2", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -4981,6 +4987,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "r3bl_tui" version = "0.7.6" @@ -5197,16 +5209,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] name = "redox_syscall" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -5229,7 +5241,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.14", - "regex-syntax 0.8.9", + "regex-syntax 0.8.10", ] [[package]] @@ -5249,7 +5261,7 @@ checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.9", + "regex-syntax 0.8.10", ] [[package]] @@ -5260,9 +5272,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" @@ -5292,7 +5304,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "serde", "serde_json", @@ -5355,6 +5367,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "roff" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf2048e0e979efb2ca7b91c4f1a8d77c91853e9b987c94c555668a8994915ad" + [[package]] name = "rpassword" version = "7.4.0" @@ -5369,7 +5387,7 @@ dependencies = [ [[package]] name = "rpc-toolkit" version = "0.3.2" -source = "git+https://github.com/Start9Labs/rpc-toolkit.git#39e547ff99d997c19f9b6483b28a4394ca5a07bc" +source = "git+https://github.com/Start9Labs/rpc-toolkit.git#14fb3e2e5c2bc77893022399360933917c38aa1e" dependencies = [ "async-stream", "async-trait", @@ -5466,7 +5484,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -5528,7 +5546,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -5537,14 +5555,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -5564,9 +5582,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "aws-lc-rs", "log", @@ -5584,10 +5602,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe 0.2.1", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -5620,11 +5638,11 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki 0.103.9", - "security-framework 3.5.1", + "security-framework", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -5694,9 +5712,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -5729,24 +5747,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" -dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -5755,9 +5760,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -5828,7 +5833,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -5875,7 +5880,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -5938,9 +5943,9 @@ dependencies = [ [[package]] name = "serial2" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cc76fa68e25e771492ca1e3c53d447ef0be3093e05cd3b47f4b712ba10c6f3c" +checksum = "9e1401f562d358cdfdbdf8946e51a7871ede1db68bd0fd99bedc79e400241550" dependencies = [ "cfg-if", "libc", @@ -6187,12 +6192,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6258,7 +6263,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rustls 0.23.36", + "rustls 0.23.37", "serde", "serde_json", "sha2 0.10.9", @@ -6281,7 +6286,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -6302,7 +6307,7 @@ dependencies = [ "sha2 0.10.9", "sqlx-core", "sqlx-postgres", - "syn 2.0.115", + "syn 2.0.117", "tokio", "url", ] @@ -6315,7 +6320,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "byteorder", "crc", "dotenvy", @@ -6367,7 +6372,7 @@ dependencies = [ "quote", "regex-syntax 0.6.29", "strsim", - "syn 2.0.115", + "syn 2.0.117", "unicode-width 0.1.14", ] @@ -6452,6 +6457,7 @@ dependencies = [ "chrono", "ciborium", "clap", + "clap_mangen", "color-eyre", "console", "console-subscriber", @@ -6540,7 +6546,7 @@ dependencies = [ "sha2 0.10.9", "sha3", "signal-hook", - "socket2 0.6.2", + "socket2 0.6.3", "socks5-impl", "sqlx", "sscanf", @@ -6638,7 +6644,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -6681,9 +6687,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.115" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -6707,7 +6713,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -6722,7 +6728,7 @@ dependencies = [ "once_cell", "onig", "plist", - "regex-syntax 0.8.9", + "regex-syntax 0.8.10", "serde", "serde_derive", "serde_json", @@ -6737,7 +6743,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -6777,14 +6783,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.25.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -6814,7 +6820,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.60.2", ] @@ -6865,7 +6871,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -6876,7 +6882,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -6940,9 +6946,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -6955,9 +6961,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", @@ -6965,7 +6971,7 @@ dependencies = [ "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.2", + "socket2 0.6.3", "tokio-macros", "tracing", "windows-sys 0.61.2", @@ -6973,13 +6979,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -7009,7 +7015,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.36", + "rustls 0.23.37", "tokio", ] @@ -7111,7 +7117,7 @@ dependencies = [ "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.15", ] [[package]] @@ -7132,6 +7138,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.0.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" @@ -7143,28 +7158,28 @@ dependencies = [ "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "8ca1a40644a28bce036923f6a431df0b34236949d111cc07cb6dca830c9ef2e1" dependencies = [ "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "toml_datetime 1.0.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.0", ] [[package]] name = "toml_parser" -version = "1.0.8+spec-1.1.0" +version = "1.0.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" +checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420" dependencies = [ - "winnow", + "winnow 1.0.0", ] [[package]] @@ -7175,15 +7190,15 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.0.7+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d" [[package]] name = "tonic" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a286e33f82f8a1ee2df63f4fa35c0becf4a85a0cb03091a15fd7bf0b402dc94a" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" dependencies = [ "async-trait", "axum", @@ -7198,7 +7213,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "socket2 0.6.2", + "socket2 0.6.3", "sync_wrapper", "tokio", "tokio-stream", @@ -7210,9 +7225,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c55a2d6a14174563de34409c9f92ff981d006f56da9c6ecd40d9d4a31500b0" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" dependencies = [ "bytes", "prost", @@ -7244,7 +7259,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-util", "http", @@ -7300,7 +7315,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -7398,7 +7413,7 @@ checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "termcolor", ] @@ -7455,7 +7470,7 @@ checksum = "076a02dc54dd46795c2e9c8282ed40bcfb1e22747e955de9389a1de28190fb26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -7472,13 +7487,13 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uds_windows" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset 0.9.1", "tempfile", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -7501,9 +7516,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-linebreak" @@ -7607,11 +7622,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.20.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", "serde_core", "wasm-bindgen", @@ -7661,7 +7676,7 @@ checksum = "2a3bfb04fd13da4fc8df24709b7a0949667f43c63691d9fecddf1d3be8af5099" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -7739,9 +7754,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -7752,9 +7767,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", "futures-util", @@ -7766,9 +7781,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7776,22 +7791,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] @@ -7837,7 +7852,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "hashbrown 0.15.5", "indexmap 2.13.0", "semver", @@ -7918,9 +7933,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -8052,7 +8067,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -8063,7 +8078,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -8400,9 +8415,18 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" dependencies = [ "memchr", ] @@ -8456,7 +8480,7 @@ dependencies = [ "heck 0.5.0", "indexmap 2.13.0", "prettyplease", - "syn 2.0.115", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -8472,7 +8496,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -8484,7 +8508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.10.0", + "bitflags 2.11.0", "indexmap 2.13.0", "log", "serde", @@ -8611,7 +8635,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -8701,15 +8725,15 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "synstructure", ] [[package]] name = "zbus" -version = "5.13.2" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfeff997a0aaa3eb20c4652baf788d2dfa6d2839a0ead0b3ff69ce2f9c4bdd1" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" dependencies = [ "async-broadcast", "async-executor", @@ -8727,14 +8751,14 @@ dependencies = [ "hex", "libc", "ordered-stream", - "rustix 1.1.3", + "rustix 1.1.4", "serde", "serde_repr", "tracing", "uds_windows", "uuid", "windows-sys 0.61.2", - "winnow", + "winnow 0.7.15", "zbus_macros", "zbus_names", "zvariant", @@ -8742,14 +8766,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.13.2" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bbd5a90dbe8feee5b13def448427ae314ccd26a49cac47905cafefb9ff846f1" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "zbus_names", "zvariant", "zvariant_utils", @@ -8762,28 +8786,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" dependencies = [ "serde", - "winnow", + "winnow 0.7.15", "zvariant", ] [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -8803,7 +8827,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "synstructure", ] @@ -8824,7 +8848,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -8857,7 +8881,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", ] [[package]] @@ -8896,28 +8920,28 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.9.2" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b64ef4f40c7951337ddc7023dd03528a57a3ce3408ee9da5e948bd29b232c4" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" dependencies = [ "endi", "enumflags2", "serde", - "winnow", + "winnow 0.7.15", "zvariant_derive", "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "5.9.2" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484d5d975eb7afb52cc6b929c13d3719a20ad650fea4120e6310de3fc55e415c" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.115", + "syn 2.0.117", "zvariant_utils", ] @@ -8930,6 +8954,6 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.115", - "winnow", + "syn 2.0.117", + "winnow 0.7.15", ] diff --git a/core/Cargo.toml b/core/Cargo.toml index 581ea58e2..7fe67b2e3 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -63,7 +63,7 @@ async-compression = { version = "0.4.32", features = [ ] } async-stream = "0.3.5" async-trait = "0.1.74" -axum = { version = "0.8.4", features = ["ws", "http2"] } +axum = { version = "0.8.4", features = ["http2", "ws"] } backtrace-on-stack-overflow = { version = "0.3.0", optional = true } base32 = "0.5.0" base64 = "0.22.1" @@ -100,6 +100,7 @@ fd-lock-rs = "0.1.4" form_urlencoded = "1.2.1" futures = "0.3.28" gpt = "4.1.0" +hashing-serializer = "0.1.1" hex = "0.4.3" hickory-server = { version = "0.25.2", features = ["resolver"] } hmac = "0.12.1" @@ -182,16 +183,16 @@ r3bl_tui = "0.7.6" rand = "0.9.2" regex = "1.10.2" reqwest = { version = "0.12.25", features = [ + "http2", "json", "socks", "stream", - "http2", ] } reqwest_cookie_store = "0.9.0" rpassword = "7.2.0" +rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git" } rust-argon2 = "3.0.0" rust-i18n = "3.1.5" -rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git" } semver = { version = "1.0.20", features = ["serde"] } serde = { version = "1.0", features = ["derive", "rc"] } serde_cbor = { package = "ciborium", version = "0.2.1" } @@ -232,7 +233,9 @@ 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" + +[dev-dependencies] +clap_mangen = "0.2.33" [target.'cfg(target_os = "linux")'.dependencies] procfs = "0.18.0" diff --git a/core/run-tests.sh b/core/run-tests.sh index f7e4de3df..d8340400f 100755 --- a/core/run-tests.sh +++ b/core/run-tests.sh @@ -41,5 +41,5 @@ fi echo "FEATURES=\"$FEATURES\"" echo "RUSTFLAGS=\"$RUSTFLAGS\"" -rust-zig-builder cargo test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=test,$FEATURES --workspace --locked --lib -- --skip export_bindings_ +rust-zig-builder cargo test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=test,$FEATURES --workspace --locked --lib -- --skip export_ rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /usr/local/cargo" From b1b7d2fa705bc59f91f3c6a55693d4125d1b9995 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Wed, 18 Mar 2026 23:47:17 -0600 Subject: [PATCH 08/53] feat: add xml file helper to SDK --- sdk/package/lib/util/fileHelper.ts | 39 ++++++++++++++++++ sdk/package/package-lock.json | 63 ++++++++++++++++++++++++++++++ sdk/package/package.json | 1 + 3 files changed, 103 insertions(+) diff --git a/sdk/package/lib/util/fileHelper.ts b/sdk/package/lib/util/fileHelper.ts index 1bcde0c90..44012b9ba 100644 --- a/sdk/package/lib/util/fileHelper.ts +++ b/sdk/package/lib/util/fileHelper.ts @@ -2,6 +2,12 @@ import { z } from 'zod' import * as YAML from 'yaml' import * as TOML from '@iarna/toml' import * as INI from 'ini' +import { + XMLParser, + XMLBuilder, + type X2jOptions, + type XmlBuilderOptions, +} from 'fast-xml-parser' import * as T from '../../../base/lib/types' import * as fs from 'node:fs/promises' import { asError, deepEqual } from '../../../base/lib/util' @@ -618,6 +624,39 @@ export class FileHelper { transformers, ) } + + /** + * Create a File Helper for an .xml file. + * + * Supports optional parser/builder options from `fast-xml-parser`. + */ + static xml>( + path: ToPath, + shape: Validator, A>, + options?: { parser?: X2jOptions; builder?: XmlBuilderOptions }, + ): FileHelper + static xml>( + path: ToPath, + shape: Validator, + options: { parser?: X2jOptions; builder?: XmlBuilderOptions }, + transformers: Transformers, Transformed, A>, + ): FileHelper + static xml>( + path: ToPath, + shape: Validator, + options?: { parser?: X2jOptions; builder?: XmlBuilderOptions }, + transformers?: Transformers, Transformed, A>, + ): FileHelper { + const parser = new XMLParser(options?.parser) + const builder = new XMLBuilder(options?.builder) + return FileHelper.rawTransformed, Transformed>( + path, + (inData) => builder.build(inData), + (inString) => parser.parse(inString), + (data) => shape.parse(data), + transformers, + ) + } } export default FileHelper diff --git a/sdk/package/package-lock.json b/sdk/package/package-lock.json index 2e49b06f3..6582cae3e 100644 --- a/sdk/package/package-lock.json +++ b/sdk/package/package-lock.json @@ -14,6 +14,7 @@ "@noble/hashes": "^1.7.2", "@types/ini": "^4.1.1", "deep-equality-data-structures": "^2.0.0", + "fast-xml-parser": "^5.5.6", "ini": "^5.0.0", "isomorphic-fetch": "^3.0.0", "mime": "^4.0.7", @@ -2517,6 +2518,41 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-xml-builder": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz", + "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.1.3" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.6.tgz", + "integrity": "sha512-3+fdZyBRVg29n4rXP0joHthhcHdPUHaIC16cuyyd1iLsuaO6Vea36MPrxgAzbZna8lhvZeRL8Bc9GP56/J9xEw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.1.4", + "path-expression-matcher": "^1.1.3", + "strnum": "^2.1.2" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -4129,6 +4165,21 @@ "node": ">=8" } }, + "node_modules/path-expression-matcher": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz", + "integrity": "sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -4643,6 +4694,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", + "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/sdk/package/package.json b/sdk/package/package.json index 64dbf2d21..855389278 100644 --- a/sdk/package/package.json +++ b/sdk/package/package.json @@ -36,6 +36,7 @@ "@noble/hashes": "^1.7.2", "@types/ini": "^4.1.1", "deep-equality-data-structures": "^2.0.0", + "fast-xml-parser": "^5.5.6", "ini": "^5.0.0", "isomorphic-fetch": "^3.0.0", "mime": "^4.0.7", From bcdeabfe851c08d7c7891b067744896860c3d330 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Wed, 18 Mar 2026 23:48:13 -0600 Subject: [PATCH 09/53] fix: clap CLI definitions and manpage generation - add #[group(skip)] to all Parser-derived structs - fix conflicts_with and arg definitions for correct CLI behavior - refactor bin entry points to support manpage generation --- core/build/build-manpage.sh | 44 +++++++ .../man/start-cli/start-cli-auth-get-pubkey.1 | 13 ++ core/man/start-cli/start-cli-auth-login.1 | 13 ++ core/man/start-cli/start-cli-auth-logout.1 | 16 +++ .../start-cli/start-cli-auth-reset-password.1 | 13 ++ .../start-cli/start-cli-auth-session-kill.1 | 16 +++ .../start-cli/start-cli-auth-session-list.1 | 16 +++ core/man/start-cli/start-cli-auth-session.1 | 20 +++ core/man/start-cli/start-cli-auth.1 | 29 +++++ core/man/start-cli/start-cli-backup-create.1 | 25 ++++ .../start-cli-backup-target-cifs-add.1 | 25 ++++ .../start-cli-backup-target-cifs-remove.1 | 16 +++ .../start-cli-backup-target-cifs-update.1 | 28 ++++ .../start-cli/start-cli-backup-target-cifs.1 | 23 ++++ .../start-cli/start-cli-backup-target-info.1 | 25 ++++ .../start-cli/start-cli-backup-target-list.1 | 16 +++ .../start-cli/start-cli-backup-target-mount.1 | 25 ++++ .../start-cli-backup-target-umount.1 | 16 +++ core/man/start-cli/start-cli-backup-target.1 | 29 +++++ core/man/start-cli/start-cli-backup.1 | 20 +++ core/man/start-cli/start-cli-db-apply.1 | 22 ++++ core/man/start-cli/start-cli-db-dump.1 | 22 ++++ core/man/start-cli/start-cli-db-put-ui.1 | 22 ++++ core/man/start-cli/start-cli-db-put.1 | 17 +++ core/man/start-cli/start-cli-db.1 | 23 ++++ .../start-cli-diagnostic-disk-forget.1 | 13 ++ .../start-cli-diagnostic-disk-repair.1 | 13 ++ .../man/start-cli/start-cli-diagnostic-disk.1 | 20 +++ .../start-cli/start-cli-diagnostic-error.1 | 13 ++ .../start-cli-diagnostic-kernel-logs.1 | 28 ++++ .../man/start-cli/start-cli-diagnostic-logs.1 | 28 ++++ .../start-cli/start-cli-diagnostic-rebuild.1 | 13 ++ .../start-cli/start-cli-diagnostic-restart.1 | 13 ++ core/man/start-cli/start-cli-diagnostic.1 | 32 +++++ core/man/start-cli/start-cli-disk-list.1 | 16 +++ core/man/start-cli/start-cli-disk-repair.1 | 13 ++ core/man/start-cli/start-cli-disk.1 | 20 +++ core/man/start-cli/start-cli-echo.1 | 16 +++ core/man/start-cli/start-cli-flash-os.1 | 32 +++++ core/man/start-cli/start-cli-git-info.1 | 13 ++ .../start-cli/start-cli-init-kernel-logs.1 | 28 ++++ core/man/start-cli/start-cli-init-key.1 | 13 ++ core/man/start-cli/start-cli-init-logs.1 | 28 ++++ core/man/start-cli/start-cli-init-subscribe.1 | 13 ++ core/man/start-cli/start-cli-init.1 | 23 ++++ core/man/start-cli/start-cli-kiosk-disable.1 | 13 ++ core/man/start-cli/start-cli-kiosk-enable.1 | 13 ++ core/man/start-cli/start-cli-kiosk.1 | 20 +++ core/man/start-cli/start-cli-net-acme-init.1 | 19 +++ .../man/start-cli/start-cli-net-acme-remove.1 | 16 +++ core/man/start-cli/start-cli-net-acme.1 | 20 +++ .../start-cli/start-cli-net-dns-dump-table.1 | 16 +++ core/man/start-cli/start-cli-net-dns-query.1 | 19 +++ .../start-cli/start-cli-net-dns-set-static.1 | 16 +++ core/man/start-cli/start-cli-net-dns.1 | 23 ++++ .../start-cli-net-forward-dump-table.1 | 15 +++ core/man/start-cli/start-cli-net-forward.1 | 16 +++ .../start-cli-net-gateway-check-dns.1 | 19 +++ .../start-cli-net-gateway-check-port.1 | 22 ++++ .../start-cli/start-cli-net-gateway-forget.1 | 16 +++ .../start-cli/start-cli-net-gateway-list.1 | 16 +++ ...art-cli-net-gateway-set-default-outbound.1 | 16 +++ .../start-cli-net-gateway-set-name.1 | 19 +++ core/man/start-cli/start-cli-net-gateway.1 | 32 +++++ core/man/start-cli/start-cli-net-tunnel-add.1 | 35 +++++ .../start-cli/start-cli-net-tunnel-remove.1 | 16 +++ core/man/start-cli/start-cli-net-tunnel.1 | 20 +++ .../start-cli-net-vhost-add-passthrough.1 | 27 ++++ .../start-cli-net-vhost-dump-table.1 | 15 +++ .../start-cli-net-vhost-list-passthrough.1 | 15 +++ .../start-cli-net-vhost-remove-passthrough.1 | 18 +++ core/man/start-cli/start-cli-net-vhost.1 | 22 ++++ core/man/start-cli/start-cli-net.1 | 32 +++++ .../start-cli/start-cli-notification-create.1 | 25 ++++ .../start-cli/start-cli-notification-list.1 | 22 ++++ .../start-cli-notification-mark-seen-before.1 | 16 +++ .../start-cli-notification-mark-seen.1 | 16 +++ .../start-cli-notification-mark-unseen.1 | 16 +++ .../start-cli-notification-remove-before.1 | 16 +++ .../start-cli/start-cli-notification-remove.1 | 16 +++ core/man/start-cli/start-cli-notification.1 | 35 +++++ .../start-cli-package-action-clear-task.1 | 22 ++++ .../start-cli-package-action-get-input.1 | 22 ++++ .../start-cli/start-cli-package-action-run.1 | 25 ++++ core/man/start-cli/start-cli-package-action.1 | 23 ++++ core/man/start-cli/start-cli-package-attach.1 | 33 +++++ .../start-cli-package-backup-restore.1 | 22 ++++ core/man/start-cli/start-cli-package-backup.1 | 17 +++ .../start-cli-package-cancel-install.1 | 16 +++ ...-package-host-address-domain-private-add.1 | 19 +++ ...ckage-host-address-domain-private-remove.1 | 16 +++ ...-cli-package-host-address-domain-private.1 | 19 +++ ...i-package-host-address-domain-public-add.1 | 25 ++++ ...ackage-host-address-domain-public-remove.1 | 16 +++ ...t-cli-package-host-address-domain-public.1 | 19 +++ .../start-cli-package-host-address-domain.1 | 17 +++ .../start-cli-package-host-address-list.1 | 16 +++ .../start-cli-package-host-address.1 | 21 +++ .../start-cli-package-host-binding-list.1 | 16 +++ ...package-host-binding-set-address-enabled.1 | 32 +++++ .../start-cli-package-host-binding.1 | 22 ++++ core/man/start-cli/start-cli-package-host.1 | 21 +++ .../man/start-cli/start-cli-package-install.1 | 22 ++++ .../start-cli-package-installed-version.1 | 19 +++ core/man/start-cli/start-cli-package-list.1 | 16 +++ core/man/start-cli/start-cli-package-logs.1 | 31 +++++ .../man/start-cli/start-cli-package-rebuild.1 | 16 +++ .../man/start-cli/start-cli-package-restart.1 | 16 +++ .../start-cli-package-set-outbound-gateway.1 | 19 +++ core/man/start-cli/start-cli-package-start.1 | 16 +++ core/man/start-cli/start-cli-package-stats.1 | 16 +++ core/man/start-cli/start-cli-package-stop.1 | 16 +++ .../start-cli/start-cli-package-uninstall.1 | 22 ++++ core/man/start-cli/start-cli-package.1 | 61 +++++++++ core/man/start-cli/start-cli-pubkey.1 | 13 ++ .../start-cli/start-cli-registry-admin-add.1 | 19 +++ .../start-cli/start-cli-registry-admin-list.1 | 16 +++ .../start-cli-registry-admin-remove.1 | 16 +++ .../start-cli-registry-admin-signer-add.1 | 25 ++++ .../start-cli-registry-admin-signer-edit.1 | 31 +++++ .../start-cli-registry-admin-signer-list.1 | 16 +++ .../start-cli-registry-admin-signer.1 | 23 ++++ core/man/start-cli/start-cli-registry-admin.1 | 26 ++++ .../start-cli/start-cli-registry-db-apply.1 | 19 +++ .../start-cli/start-cli-registry-db-dump.1 | 22 ++++ core/man/start-cli/start-cli-registry-db.1 | 20 +++ core/man/start-cli/start-cli-registry-index.1 | 16 +++ .../start-cli-registry-info-set-icon.1 | 16 +++ .../start-cli-registry-info-set-name.1 | 16 +++ core/man/start-cli/start-cli-registry-info.1 | 23 ++++ .../start-cli-registry-os-asset-add.1 | 25 ++++ .../start-cli-registry-os-asset-get-img.1 | 25 ++++ .../start-cli-registry-os-asset-get-iso.1 | 25 ++++ ...start-cli-registry-os-asset-get-squashfs.1 | 25 ++++ .../start-cli-registry-os-asset-get.1 | 23 ++++ .../start-cli-registry-os-asset-remove.1 | 12 ++ .../start-cli-registry-os-asset-sign.1 | 22 ++++ .../start-cli/start-cli-registry-os-asset.1 | 25 ++++ .../start-cli/start-cli-registry-os-index.1 | 16 +++ .../start-cli-registry-os-version-add.1 | 25 ++++ .../start-cli-registry-os-version-get.1 | 28 ++++ .../start-cli-registry-os-version-remove.1 | 16 +++ ...start-cli-registry-os-version-signer-add.1 | 19 +++ ...tart-cli-registry-os-version-signer-list.1 | 19 +++ ...rt-cli-registry-os-version-signer-remove.1 | 19 +++ .../start-cli-registry-os-version-signer.1 | 23 ++++ .../start-cli/start-cli-registry-os-version.1 | 26 ++++ core/man/start-cli/start-cli-registry-os.1 | 23 ++++ .../start-cli-registry-package-add-mirror.1 | 22 ++++ .../start-cli-registry-package-add.1 | 22 ++++ ...li-registry-package-category-add-package.1 | 19 +++ .../start-cli-registry-package-category-add.1 | 19 +++ ...start-cli-registry-package-category-list.1 | 15 +++ ...registry-package-category-remove-package.1 | 19 +++ ...art-cli-registry-package-category-remove.1 | 16 +++ .../start-cli-registry-package-category.1 | 28 ++++ .../start-cli-registry-package-download.1 | 22 ++++ .../start-cli-registry-package-get.1 | 40 ++++++ .../start-cli-registry-package-index.1 | 16 +++ ...start-cli-registry-package-remove-mirror.1 | 22 ++++ .../start-cli-registry-package-remove.1 | 22 ++++ .../start-cli-registry-package-signer-add.1 | 25 ++++ .../start-cli-registry-package-signer-list.1 | 19 +++ ...start-cli-registry-package-signer-remove.1 | 19 +++ .../start-cli-registry-package-signer.1 | 23 ++++ .../start-cli/start-cli-registry-package.1 | 41 ++++++ core/man/start-cli/start-cli-registry.1 | 32 +++++ core/man/start-cli/start-cli-s9pk-convert.1 | 16 +++ .../start-cli/start-cli-s9pk-edit-add-image.1 | 37 ++++++ .../start-cli/start-cli-s9pk-edit-manifest.1 | 19 +++ core/man/start-cli/start-cli-s9pk-edit.1 | 23 ++++ .../start-cli/start-cli-s9pk-inspect-cat.1 | 16 +++ .../start-cli-s9pk-inspect-commitment.1 | 16 +++ .../start-cli-s9pk-inspect-file-tree.1 | 16 +++ .../start-cli-s9pk-inspect-manifest.1 | 16 +++ core/man/start-cli/start-cli-s9pk-inspect.1 | 29 +++++ .../start-cli-s9pk-list-ingredients.1 | 37 ++++++ core/man/start-cli/start-cli-s9pk-pack.1 | 37 ++++++ core/man/start-cli/start-cli-s9pk-publish.1 | 16 +++ core/man/start-cli/start-cli-s9pk-select.1 | 16 +++ core/man/start-cli/start-cli-s9pk.1 | 35 +++++ .../start-cli/start-cli-server-clear-smtp.1 | 13 ++ .../start-cli/start-cli-server-device-info.1 | 16 +++ .../start-cli-server-experimental-governor.1 | 19 +++ .../start-cli-server-experimental-zram.1 | 16 +++ .../start-cli/start-cli-server-experimental.1 | 20 +++ ...i-server-host-address-domain-private-add.1 | 19 +++ ...erver-host-address-domain-private-remove.1 | 16 +++ ...t-cli-server-host-address-domain-private.1 | 19 +++ ...li-server-host-address-domain-public-add.1 | 25 ++++ ...server-host-address-domain-public-remove.1 | 16 +++ ...rt-cli-server-host-address-domain-public.1 | 19 +++ .../start-cli-server-host-address-domain.1 | 17 +++ .../start-cli-server-host-address-list.1 | 16 +++ .../start-cli/start-cli-server-host-address.1 | 18 +++ .../start-cli-server-host-binding-list.1 | 16 +++ ...-server-host-binding-set-address-enabled.1 | 32 +++++ .../start-cli/start-cli-server-host-binding.1 | 19 +++ core/man/start-cli/start-cli-server-host.1 | 18 +++ .../start-cli/start-cli-server-kernel-logs.1 | 28 ++++ core/man/start-cli/start-cli-server-logs.1 | 28 ++++ core/man/start-cli/start-cli-server-metrics.1 | 16 +++ core/man/start-cli/start-cli-server-rebuild.1 | 13 ++ core/man/start-cli/start-cli-server-restart.1 | 13 ++ .../start-cli-server-set-echoip-urls.1 | 16 +++ .../start-cli/start-cli-server-set-hostname.1 | 19 +++ .../start-cli/start-cli-server-set-keyboard.1 | 28 ++++ .../start-cli/start-cli-server-set-language.1 | 16 +++ .../man/start-cli/start-cli-server-set-smtp.1 | 41 ++++++ .../man/start-cli/start-cli-server-shutdown.1 | 13 ++ .../start-cli/start-cli-server-test-smtp.1 | 44 +++++++ core/man/start-cli/start-cli-server-time.1 | 16 +++ .../start-cli-server-update-firmware.1 | 13 ++ core/man/start-cli/start-cli-server-update.1 | 22 ++++ core/man/start-cli/start-cli-server.1 | 71 +++++++++++ core/man/start-cli/start-cli-setup-cifs.1 | 12 ++ core/man/start-cli/start-cli-setup-disk.1 | 12 ++ core/man/start-cli/start-cli-setup-logs.1 | 28 ++++ core/man/start-cli/start-cli-setup.1 | 21 +++ core/man/start-cli/start-cli-ssh-add.1 | 16 +++ core/man/start-cli/start-cli-ssh-list.1 | 16 +++ core/man/start-cli/start-cli-ssh-remove.1 | 16 +++ core/man/start-cli/start-cli-ssh.1 | 23 ++++ core/man/start-cli/start-cli-state.1 | 13 ++ .../start-cli-tunnel-auth-get-pubkey.1 | 13 ++ .../start-cli/start-cli-tunnel-auth-key-add.1 | 19 +++ .../start-cli-tunnel-auth-key-list.1 | 16 +++ .../start-cli-tunnel-auth-key-remove.1 | 16 +++ .../man/start-cli/start-cli-tunnel-auth-key.1 | 22 ++++ .../start-cli/start-cli-tunnel-auth-login.1 | 13 ++ .../start-cli/start-cli-tunnel-auth-logout.1 | 16 +++ .../start-cli-tunnel-auth-reset-password.1 | 13 ++ .../start-cli-tunnel-auth-session-kill.1 | 16 +++ .../start-cli-tunnel-auth-session-list.1 | 16 +++ .../start-cli/start-cli-tunnel-auth-session.1 | 20 +++ .../start-cli-tunnel-auth-set-password.1 | 13 ++ core/man/start-cli/start-cli-tunnel-auth.1 | 34 +++++ .../man/start-cli/start-cli-tunnel-db-apply.1 | 19 +++ core/man/start-cli/start-cli-tunnel-db-dump.1 | 22 ++++ core/man/start-cli/start-cli-tunnel-db.1 | 20 +++ .../start-cli/start-cli-tunnel-device-add.1 | 22 ++++ .../start-cli/start-cli-tunnel-device-list.1 | 19 +++ .../start-cli-tunnel-device-remove.1 | 19 +++ .../start-cli-tunnel-device-show-config.1 | 22 ++++ core/man/start-cli/start-cli-tunnel-device.1 | 26 ++++ .../start-cli-tunnel-port-forward-add.1 | 22 ++++ .../start-cli-tunnel-port-forward-remove.1 | 16 +++ ...tart-cli-tunnel-port-forward-set-enabled.1 | 19 +++ ...art-cli-tunnel-port-forward-update-label.1 | 19 +++ .../start-cli/start-cli-tunnel-port-forward.1 | 25 ++++ core/man/start-cli/start-cli-tunnel-restart.1 | 13 ++ .../start-cli/start-cli-tunnel-subnet-add.1 | 16 +++ .../start-cli-tunnel-subnet-remove.1 | 13 ++ core/man/start-cli/start-cli-tunnel-subnet.1 | 23 ++++ .../start-cli/start-cli-tunnel-update-apply.1 | 16 +++ .../start-cli/start-cli-tunnel-update-check.1 | 16 +++ core/man/start-cli/start-cli-tunnel-update.1 | 19 +++ .../start-cli/start-cli-tunnel-web-disable.1 | 13 ++ .../start-cli/start-cli-tunnel-web-enable.1 | 13 ++ ...tart-cli-tunnel-web-generate-certificate.1 | 16 +++ .../start-cli-tunnel-web-get-available-ips.1 | 16 +++ .../start-cli-tunnel-web-get-certificate.1 | 16 +++ .../start-cli-tunnel-web-get-listen.1 | 16 +++ .../start-cli-tunnel-web-import-certificate.1 | 13 ++ .../man/start-cli/start-cli-tunnel-web-init.1 | 13 ++ .../start-cli-tunnel-web-set-listen.1 | 16 +++ .../start-cli/start-cli-tunnel-web-uninit.1 | 13 ++ core/man/start-cli/start-cli-tunnel-web.1 | 43 +++++++ core/man/start-cli/start-cli-tunnel.1 | 35 +++++ core/man/start-cli/start-cli-util-b3sum.1 | 19 +++ core/man/start-cli/start-cli-util.1 | 17 +++ core/man/start-cli/start-cli-wifi-add.1 | 19 +++ .../start-cli/start-cli-wifi-available-get.1 | 16 +++ core/man/start-cli/start-cli-wifi-available.1 | 17 +++ core/man/start-cli/start-cli-wifi-connect.1 | 16 +++ .../start-cli/start-cli-wifi-country-set.1 | 16 +++ core/man/start-cli/start-cli-wifi-country.1 | 17 +++ core/man/start-cli/start-cli-wifi-get.1 | 16 +++ core/man/start-cli/start-cli-wifi-remove.1 | 16 +++ .../start-cli/start-cli-wifi-set-enabled.1 | 16 +++ core/man/start-cli/start-cli-wifi.1 | 35 +++++ core/man/start-cli/start-cli.1 | 120 ++++++++++++++++++ .../start-container-action-clear-tasks.1 | 18 +++ .../start-container-action-clear.1 | 15 +++ .../start-container-action-get-input.1 | 21 +++ .../start-container-action-run.1 | 24 ++++ .../start-container/start-container-action.1 | 21 +++ .../start-container-check-dependencies.1 | 15 +++ .../start-container/start-container-echo.1 | 15 +++ .../start-container-get-data-version.1 | 12 ++ .../start-container-get-dependencies.1 | 12 ++ .../start-container-get-os-ip.1 | 12 ++ .../start-container-get-status.1 | 15 +++ .../start-container-git-info.1 | 12 ++ .../start-container-plugin-url.1 | 12 ++ .../start-container/start-container-plugin.1 | 15 +++ .../start-container/start-container-rebuild.1 | 12 ++ .../start-container/start-container-restart.1 | 12 ++ .../start-container-set-data-version.1 | 15 +++ .../start-container-set-dependencies.1 | 15 +++ .../start-container-set-main-status.1 | 15 +++ .../start-container-shutdown.1 | 12 ++ .../start-container-subcontainer-create-fs.1 | 18 +++ .../start-container-subcontainer-destroy-fs.1 | 15 +++ ...tart-container-subcontainer-exec-command.1 | 39 ++++++ .../start-container-subcontainer-exec.1 | 39 ++++++ ...start-container-subcontainer-launch-init.1 | 39 ++++++ .../start-container-subcontainer-launch.1 | 39 ++++++ .../start-container-subcontainer.1 | 25 ++++ core/man/start-container/start-container.1 | 53 ++++++++ .../start-registry/start-registry-admin-add.1 | 19 +++ .../start-registry-admin-list.1 | 16 +++ .../start-registry-admin-remove.1 | 16 +++ .../start-registry-admin-signer-add.1 | 25 ++++ .../start-registry-admin-signer-edit.1 | 31 +++++ .../start-registry-admin-signer-list.1 | 16 +++ .../start-registry-admin-signer.1 | 23 ++++ .../man/start-registry/start-registry-admin.1 | 26 ++++ .../start-registry/start-registry-db-apply.1 | 19 +++ .../start-registry/start-registry-db-dump.1 | 22 ++++ core/man/start-registry/start-registry-db.1 | 20 +++ .../man/start-registry/start-registry-index.1 | 16 +++ .../start-registry-info-set-icon.1 | 16 +++ .../start-registry-info-set-name.1 | 16 +++ core/man/start-registry/start-registry-info.1 | 23 ++++ .../start-registry-os-asset-add.1 | 25 ++++ .../start-registry-os-asset-get-img.1 | 25 ++++ .../start-registry-os-asset-get-iso.1 | 25 ++++ .../start-registry-os-asset-get-squashfs.1 | 25 ++++ .../start-registry-os-asset-get.1 | 23 ++++ .../start-registry-os-asset-remove.1 | 12 ++ .../start-registry-os-asset-sign.1 | 22 ++++ .../start-registry/start-registry-os-asset.1 | 25 ++++ .../start-registry/start-registry-os-index.1 | 16 +++ .../start-registry-os-version-add.1 | 25 ++++ .../start-registry-os-version-get.1 | 28 ++++ .../start-registry-os-version-remove.1 | 16 +++ .../start-registry-os-version-signer-add.1 | 19 +++ .../start-registry-os-version-signer-list.1 | 19 +++ .../start-registry-os-version-signer-remove.1 | 19 +++ .../start-registry-os-version-signer.1 | 23 ++++ .../start-registry-os-version.1 | 26 ++++ core/man/start-registry/start-registry-os.1 | 23 ++++ .../start-registry-package-add-mirror.1 | 22 ++++ .../start-registry-package-add.1 | 22 ++++ ...rt-registry-package-category-add-package.1 | 19 +++ .../start-registry-package-category-add.1 | 19 +++ .../start-registry-package-category-list.1 | 15 +++ ...registry-package-category-remove-package.1 | 19 +++ .../start-registry-package-category-remove.1 | 16 +++ .../start-registry-package-category.1 | 28 ++++ .../start-registry-package-download.1 | 22 ++++ .../start-registry-package-get.1 | 40 ++++++ .../start-registry-package-index.1 | 16 +++ .../start-registry-package-remove-mirror.1 | 22 ++++ .../start-registry-package-remove.1 | 22 ++++ .../start-registry-package-signer-add.1 | 25 ++++ .../start-registry-package-signer-list.1 | 19 +++ .../start-registry-package-signer-remove.1 | 19 +++ .../start-registry-package-signer.1 | 23 ++++ .../start-registry/start-registry-package.1 | 41 ++++++ core/man/start-registry/start-registry.1 | 66 ++++++++++ .../start-tunnel-auth-get-pubkey.1 | 13 ++ .../start-tunnel/start-tunnel-auth-key-add.1 | 19 +++ .../start-tunnel/start-tunnel-auth-key-list.1 | 16 +++ .../start-tunnel-auth-key-remove.1 | 16 +++ core/man/start-tunnel/start-tunnel-auth-key.1 | 22 ++++ .../start-tunnel/start-tunnel-auth-login.1 | 13 ++ .../start-tunnel/start-tunnel-auth-logout.1 | 16 +++ .../start-tunnel-auth-reset-password.1 | 13 ++ .../start-tunnel-auth-session-kill.1 | 16 +++ .../start-tunnel-auth-session-list.1 | 16 +++ .../start-tunnel/start-tunnel-auth-session.1 | 20 +++ .../start-tunnel-auth-set-password.1 | 13 ++ core/man/start-tunnel/start-tunnel-auth.1 | 34 +++++ core/man/start-tunnel/start-tunnel-db-apply.1 | 19 +++ core/man/start-tunnel/start-tunnel-db-dump.1 | 22 ++++ core/man/start-tunnel/start-tunnel-db.1 | 20 +++ .../start-tunnel/start-tunnel-device-add.1 | 22 ++++ .../start-tunnel/start-tunnel-device-list.1 | 19 +++ .../start-tunnel/start-tunnel-device-remove.1 | 19 +++ .../start-tunnel-device-show-config.1 | 22 ++++ core/man/start-tunnel/start-tunnel-device.1 | 26 ++++ .../start-tunnel-port-forward-add.1 | 22 ++++ .../start-tunnel-port-forward-remove.1 | 16 +++ .../start-tunnel-port-forward-set-enabled.1 | 19 +++ .../start-tunnel-port-forward-update-label.1 | 19 +++ .../start-tunnel/start-tunnel-port-forward.1 | 25 ++++ core/man/start-tunnel/start-tunnel-restart.1 | 13 ++ .../start-tunnel/start-tunnel-subnet-add.1 | 16 +++ .../start-tunnel/start-tunnel-subnet-remove.1 | 13 ++ core/man/start-tunnel/start-tunnel-subnet.1 | 23 ++++ .../start-tunnel/start-tunnel-update-apply.1 | 16 +++ .../start-tunnel/start-tunnel-update-check.1 | 16 +++ core/man/start-tunnel/start-tunnel-update.1 | 19 +++ .../start-tunnel/start-tunnel-web-disable.1 | 13 ++ .../start-tunnel/start-tunnel-web-enable.1 | 13 ++ .../start-tunnel-web-generate-certificate.1 | 16 +++ .../start-tunnel-web-get-available-ips.1 | 16 +++ .../start-tunnel-web-get-certificate.1 | 16 +++ .../start-tunnel-web-get-listen.1 | 16 +++ .../start-tunnel-web-import-certificate.1 | 13 ++ core/man/start-tunnel/start-tunnel-web-init.1 | 13 ++ .../start-tunnel-web-set-listen.1 | 16 +++ .../start-tunnel/start-tunnel-web-uninit.1 | 13 ++ core/man/start-tunnel/start-tunnel-web.1 | 43 +++++++ core/man/start-tunnel/start-tunnel.1 | 69 ++++++++++ core/src/action.rs | 5 +- core/src/auth.rs | 4 + core/src/backup/backup_bulk.rs | 1 + core/src/backup/restore.rs | 5 +- core/src/backup/target/cifs.rs | 3 + core/src/backup/target/mod.rs | 3 + core/src/bins/container_cli.rs | 18 ++- core/src/bins/registry.rs | 22 +++- core/src/bins/start_cli.rs | 20 ++- core/src/bins/tunnel.rs | 41 ++++-- core/src/context/config.rs | 2 + core/src/control.rs | 1 + core/src/db/mod.rs | 4 + core/src/disk/mount/filesystem/idmapped.rs | 1 + core/src/hostname.rs | 1 + core/src/install/mod.rs | 4 + core/src/lib.rs | 1 + core/src/logs.rs | 3 + core/src/net/dns.rs | 2 + core/src/net/gateway.rs | 10 +- core/src/net/host/address.rs | 3 + core/src/net/host/binding.rs | 1 + core/src/net/host/mod.rs | 2 + core/src/net/tunnel.rs | 21 ++- core/src/net/wifi.rs | 6 +- core/src/notifications.rs | 6 +- core/src/os_install/mod.rs | 3 + core/src/registry/admin.rs | 4 + core/src/registry/context.rs | 2 + core/src/registry/db.rs | 4 + core/src/registry/info.rs | 2 + core/src/registry/os/asset/add.rs | 1 + core/src/registry/os/asset/get.rs | 1 + core/src/registry/os/asset/sign.rs | 1 + core/src/registry/os/version/mod.rs | 3 + core/src/registry/os/version/signer.rs | 2 + core/src/registry/package/add.rs | 4 + core/src/registry/package/category.rs | 4 + core/src/registry/package/get.rs | 2 + core/src/registry/package/signer.rs | 3 + core/src/s9pk/rpc.rs | 5 + core/src/s9pk/v1/mod.rs | 1 + core/src/s9pk/v2/pack.rs | 10 +- core/src/service/cli.rs | 1 + core/src/service/effects/action.rs | 8 +- core/src/service/effects/callbacks.rs | 1 + core/src/service/effects/control.rs | 2 + core/src/service/effects/dependency.rs | 3 + core/src/service/effects/net/bind.rs | 1 + core/src/service/effects/net/interface.rs | 1 + core/src/service/effects/prelude.rs | 1 + core/src/service/effects/subcontainer/mod.rs | 2 + core/src/service/effects/subcontainer/sync.rs | 1 + core/src/service/effects/system.rs | 1 + core/src/service/effects/version.rs | 1 + core/src/service/mod.rs | 2 + core/src/ssh.rs | 2 + core/src/system/mod.rs | 10 +- core/src/tunnel/auth.rs | 3 + core/src/tunnel/db.rs | 4 + core/src/tunnel/web.rs | 2 + core/src/update/mod.rs | 1 + core/src/util/rpc.rs | 1 + core/src/version/v0_3_6_alpha_0.rs | 15 ++- 471 files changed, 8753 insertions(+), 50 deletions(-) create mode 100755 core/build/build-manpage.sh create mode 100644 core/man/start-cli/start-cli-auth-get-pubkey.1 create mode 100644 core/man/start-cli/start-cli-auth-login.1 create mode 100644 core/man/start-cli/start-cli-auth-logout.1 create mode 100644 core/man/start-cli/start-cli-auth-reset-password.1 create mode 100644 core/man/start-cli/start-cli-auth-session-kill.1 create mode 100644 core/man/start-cli/start-cli-auth-session-list.1 create mode 100644 core/man/start-cli/start-cli-auth-session.1 create mode 100644 core/man/start-cli/start-cli-auth.1 create mode 100644 core/man/start-cli/start-cli-backup-create.1 create mode 100644 core/man/start-cli/start-cli-backup-target-cifs-add.1 create mode 100644 core/man/start-cli/start-cli-backup-target-cifs-remove.1 create mode 100644 core/man/start-cli/start-cli-backup-target-cifs-update.1 create mode 100644 core/man/start-cli/start-cli-backup-target-cifs.1 create mode 100644 core/man/start-cli/start-cli-backup-target-info.1 create mode 100644 core/man/start-cli/start-cli-backup-target-list.1 create mode 100644 core/man/start-cli/start-cli-backup-target-mount.1 create mode 100644 core/man/start-cli/start-cli-backup-target-umount.1 create mode 100644 core/man/start-cli/start-cli-backup-target.1 create mode 100644 core/man/start-cli/start-cli-backup.1 create mode 100644 core/man/start-cli/start-cli-db-apply.1 create mode 100644 core/man/start-cli/start-cli-db-dump.1 create mode 100644 core/man/start-cli/start-cli-db-put-ui.1 create mode 100644 core/man/start-cli/start-cli-db-put.1 create mode 100644 core/man/start-cli/start-cli-db.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-disk-forget.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-disk-repair.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-disk.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-error.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-kernel-logs.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-logs.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-rebuild.1 create mode 100644 core/man/start-cli/start-cli-diagnostic-restart.1 create mode 100644 core/man/start-cli/start-cli-diagnostic.1 create mode 100644 core/man/start-cli/start-cli-disk-list.1 create mode 100644 core/man/start-cli/start-cli-disk-repair.1 create mode 100644 core/man/start-cli/start-cli-disk.1 create mode 100644 core/man/start-cli/start-cli-echo.1 create mode 100644 core/man/start-cli/start-cli-flash-os.1 create mode 100644 core/man/start-cli/start-cli-git-info.1 create mode 100644 core/man/start-cli/start-cli-init-kernel-logs.1 create mode 100644 core/man/start-cli/start-cli-init-key.1 create mode 100644 core/man/start-cli/start-cli-init-logs.1 create mode 100644 core/man/start-cli/start-cli-init-subscribe.1 create mode 100644 core/man/start-cli/start-cli-init.1 create mode 100644 core/man/start-cli/start-cli-kiosk-disable.1 create mode 100644 core/man/start-cli/start-cli-kiosk-enable.1 create mode 100644 core/man/start-cli/start-cli-kiosk.1 create mode 100644 core/man/start-cli/start-cli-net-acme-init.1 create mode 100644 core/man/start-cli/start-cli-net-acme-remove.1 create mode 100644 core/man/start-cli/start-cli-net-acme.1 create mode 100644 core/man/start-cli/start-cli-net-dns-dump-table.1 create mode 100644 core/man/start-cli/start-cli-net-dns-query.1 create mode 100644 core/man/start-cli/start-cli-net-dns-set-static.1 create mode 100644 core/man/start-cli/start-cli-net-dns.1 create mode 100644 core/man/start-cli/start-cli-net-forward-dump-table.1 create mode 100644 core/man/start-cli/start-cli-net-forward.1 create mode 100644 core/man/start-cli/start-cli-net-gateway-check-dns.1 create mode 100644 core/man/start-cli/start-cli-net-gateway-check-port.1 create mode 100644 core/man/start-cli/start-cli-net-gateway-forget.1 create mode 100644 core/man/start-cli/start-cli-net-gateway-list.1 create mode 100644 core/man/start-cli/start-cli-net-gateway-set-default-outbound.1 create mode 100644 core/man/start-cli/start-cli-net-gateway-set-name.1 create mode 100644 core/man/start-cli/start-cli-net-gateway.1 create mode 100644 core/man/start-cli/start-cli-net-tunnel-add.1 create mode 100644 core/man/start-cli/start-cli-net-tunnel-remove.1 create mode 100644 core/man/start-cli/start-cli-net-tunnel.1 create mode 100644 core/man/start-cli/start-cli-net-vhost-add-passthrough.1 create mode 100644 core/man/start-cli/start-cli-net-vhost-dump-table.1 create mode 100644 core/man/start-cli/start-cli-net-vhost-list-passthrough.1 create mode 100644 core/man/start-cli/start-cli-net-vhost-remove-passthrough.1 create mode 100644 core/man/start-cli/start-cli-net-vhost.1 create mode 100644 core/man/start-cli/start-cli-net.1 create mode 100644 core/man/start-cli/start-cli-notification-create.1 create mode 100644 core/man/start-cli/start-cli-notification-list.1 create mode 100644 core/man/start-cli/start-cli-notification-mark-seen-before.1 create mode 100644 core/man/start-cli/start-cli-notification-mark-seen.1 create mode 100644 core/man/start-cli/start-cli-notification-mark-unseen.1 create mode 100644 core/man/start-cli/start-cli-notification-remove-before.1 create mode 100644 core/man/start-cli/start-cli-notification-remove.1 create mode 100644 core/man/start-cli/start-cli-notification.1 create mode 100644 core/man/start-cli/start-cli-package-action-clear-task.1 create mode 100644 core/man/start-cli/start-cli-package-action-get-input.1 create mode 100644 core/man/start-cli/start-cli-package-action-run.1 create mode 100644 core/man/start-cli/start-cli-package-action.1 create mode 100644 core/man/start-cli/start-cli-package-attach.1 create mode 100644 core/man/start-cli/start-cli-package-backup-restore.1 create mode 100644 core/man/start-cli/start-cli-package-backup.1 create mode 100644 core/man/start-cli/start-cli-package-cancel-install.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-domain-private-add.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-domain-private-remove.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-domain-private.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-domain-public-add.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-domain-public-remove.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-domain-public.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-domain.1 create mode 100644 core/man/start-cli/start-cli-package-host-address-list.1 create mode 100644 core/man/start-cli/start-cli-package-host-address.1 create mode 100644 core/man/start-cli/start-cli-package-host-binding-list.1 create mode 100644 core/man/start-cli/start-cli-package-host-binding-set-address-enabled.1 create mode 100644 core/man/start-cli/start-cli-package-host-binding.1 create mode 100644 core/man/start-cli/start-cli-package-host.1 create mode 100644 core/man/start-cli/start-cli-package-install.1 create mode 100644 core/man/start-cli/start-cli-package-installed-version.1 create mode 100644 core/man/start-cli/start-cli-package-list.1 create mode 100644 core/man/start-cli/start-cli-package-logs.1 create mode 100644 core/man/start-cli/start-cli-package-rebuild.1 create mode 100644 core/man/start-cli/start-cli-package-restart.1 create mode 100644 core/man/start-cli/start-cli-package-set-outbound-gateway.1 create mode 100644 core/man/start-cli/start-cli-package-start.1 create mode 100644 core/man/start-cli/start-cli-package-stats.1 create mode 100644 core/man/start-cli/start-cli-package-stop.1 create mode 100644 core/man/start-cli/start-cli-package-uninstall.1 create mode 100644 core/man/start-cli/start-cli-package.1 create mode 100644 core/man/start-cli/start-cli-pubkey.1 create mode 100644 core/man/start-cli/start-cli-registry-admin-add.1 create mode 100644 core/man/start-cli/start-cli-registry-admin-list.1 create mode 100644 core/man/start-cli/start-cli-registry-admin-remove.1 create mode 100644 core/man/start-cli/start-cli-registry-admin-signer-add.1 create mode 100644 core/man/start-cli/start-cli-registry-admin-signer-edit.1 create mode 100644 core/man/start-cli/start-cli-registry-admin-signer-list.1 create mode 100644 core/man/start-cli/start-cli-registry-admin-signer.1 create mode 100644 core/man/start-cli/start-cli-registry-admin.1 create mode 100644 core/man/start-cli/start-cli-registry-db-apply.1 create mode 100644 core/man/start-cli/start-cli-registry-db-dump.1 create mode 100644 core/man/start-cli/start-cli-registry-db.1 create mode 100644 core/man/start-cli/start-cli-registry-index.1 create mode 100644 core/man/start-cli/start-cli-registry-info-set-icon.1 create mode 100644 core/man/start-cli/start-cli-registry-info-set-name.1 create mode 100644 core/man/start-cli/start-cli-registry-info.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset-add.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset-get-img.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset-get-iso.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset-get-squashfs.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset-get.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset-remove.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset-sign.1 create mode 100644 core/man/start-cli/start-cli-registry-os-asset.1 create mode 100644 core/man/start-cli/start-cli-registry-os-index.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version-add.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version-get.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version-remove.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version-signer-add.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version-signer-list.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version-signer-remove.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version-signer.1 create mode 100644 core/man/start-cli/start-cli-registry-os-version.1 create mode 100644 core/man/start-cli/start-cli-registry-os.1 create mode 100644 core/man/start-cli/start-cli-registry-package-add-mirror.1 create mode 100644 core/man/start-cli/start-cli-registry-package-add.1 create mode 100644 core/man/start-cli/start-cli-registry-package-category-add-package.1 create mode 100644 core/man/start-cli/start-cli-registry-package-category-add.1 create mode 100644 core/man/start-cli/start-cli-registry-package-category-list.1 create mode 100644 core/man/start-cli/start-cli-registry-package-category-remove-package.1 create mode 100644 core/man/start-cli/start-cli-registry-package-category-remove.1 create mode 100644 core/man/start-cli/start-cli-registry-package-category.1 create mode 100644 core/man/start-cli/start-cli-registry-package-download.1 create mode 100644 core/man/start-cli/start-cli-registry-package-get.1 create mode 100644 core/man/start-cli/start-cli-registry-package-index.1 create mode 100644 core/man/start-cli/start-cli-registry-package-remove-mirror.1 create mode 100644 core/man/start-cli/start-cli-registry-package-remove.1 create mode 100644 core/man/start-cli/start-cli-registry-package-signer-add.1 create mode 100644 core/man/start-cli/start-cli-registry-package-signer-list.1 create mode 100644 core/man/start-cli/start-cli-registry-package-signer-remove.1 create mode 100644 core/man/start-cli/start-cli-registry-package-signer.1 create mode 100644 core/man/start-cli/start-cli-registry-package.1 create mode 100644 core/man/start-cli/start-cli-registry.1 create mode 100644 core/man/start-cli/start-cli-s9pk-convert.1 create mode 100644 core/man/start-cli/start-cli-s9pk-edit-add-image.1 create mode 100644 core/man/start-cli/start-cli-s9pk-edit-manifest.1 create mode 100644 core/man/start-cli/start-cli-s9pk-edit.1 create mode 100644 core/man/start-cli/start-cli-s9pk-inspect-cat.1 create mode 100644 core/man/start-cli/start-cli-s9pk-inspect-commitment.1 create mode 100644 core/man/start-cli/start-cli-s9pk-inspect-file-tree.1 create mode 100644 core/man/start-cli/start-cli-s9pk-inspect-manifest.1 create mode 100644 core/man/start-cli/start-cli-s9pk-inspect.1 create mode 100644 core/man/start-cli/start-cli-s9pk-list-ingredients.1 create mode 100644 core/man/start-cli/start-cli-s9pk-pack.1 create mode 100644 core/man/start-cli/start-cli-s9pk-publish.1 create mode 100644 core/man/start-cli/start-cli-s9pk-select.1 create mode 100644 core/man/start-cli/start-cli-s9pk.1 create mode 100644 core/man/start-cli/start-cli-server-clear-smtp.1 create mode 100644 core/man/start-cli/start-cli-server-device-info.1 create mode 100644 core/man/start-cli/start-cli-server-experimental-governor.1 create mode 100644 core/man/start-cli/start-cli-server-experimental-zram.1 create mode 100644 core/man/start-cli/start-cli-server-experimental.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-domain-private-add.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-domain-private-remove.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-domain-private.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-domain-public-add.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-domain-public-remove.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-domain-public.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-domain.1 create mode 100644 core/man/start-cli/start-cli-server-host-address-list.1 create mode 100644 core/man/start-cli/start-cli-server-host-address.1 create mode 100644 core/man/start-cli/start-cli-server-host-binding-list.1 create mode 100644 core/man/start-cli/start-cli-server-host-binding-set-address-enabled.1 create mode 100644 core/man/start-cli/start-cli-server-host-binding.1 create mode 100644 core/man/start-cli/start-cli-server-host.1 create mode 100644 core/man/start-cli/start-cli-server-kernel-logs.1 create mode 100644 core/man/start-cli/start-cli-server-logs.1 create mode 100644 core/man/start-cli/start-cli-server-metrics.1 create mode 100644 core/man/start-cli/start-cli-server-rebuild.1 create mode 100644 core/man/start-cli/start-cli-server-restart.1 create mode 100644 core/man/start-cli/start-cli-server-set-echoip-urls.1 create mode 100644 core/man/start-cli/start-cli-server-set-hostname.1 create mode 100644 core/man/start-cli/start-cli-server-set-keyboard.1 create mode 100644 core/man/start-cli/start-cli-server-set-language.1 create mode 100644 core/man/start-cli/start-cli-server-set-smtp.1 create mode 100644 core/man/start-cli/start-cli-server-shutdown.1 create mode 100644 core/man/start-cli/start-cli-server-test-smtp.1 create mode 100644 core/man/start-cli/start-cli-server-time.1 create mode 100644 core/man/start-cli/start-cli-server-update-firmware.1 create mode 100644 core/man/start-cli/start-cli-server-update.1 create mode 100644 core/man/start-cli/start-cli-server.1 create mode 100644 core/man/start-cli/start-cli-setup-cifs.1 create mode 100644 core/man/start-cli/start-cli-setup-disk.1 create mode 100644 core/man/start-cli/start-cli-setup-logs.1 create mode 100644 core/man/start-cli/start-cli-setup.1 create mode 100644 core/man/start-cli/start-cli-ssh-add.1 create mode 100644 core/man/start-cli/start-cli-ssh-list.1 create mode 100644 core/man/start-cli/start-cli-ssh-remove.1 create mode 100644 core/man/start-cli/start-cli-ssh.1 create mode 100644 core/man/start-cli/start-cli-state.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-get-pubkey.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-key-add.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-key-list.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-key-remove.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-key.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-login.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-logout.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-reset-password.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-session-kill.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-session-list.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-session.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth-set-password.1 create mode 100644 core/man/start-cli/start-cli-tunnel-auth.1 create mode 100644 core/man/start-cli/start-cli-tunnel-db-apply.1 create mode 100644 core/man/start-cli/start-cli-tunnel-db-dump.1 create mode 100644 core/man/start-cli/start-cli-tunnel-db.1 create mode 100644 core/man/start-cli/start-cli-tunnel-device-add.1 create mode 100644 core/man/start-cli/start-cli-tunnel-device-list.1 create mode 100644 core/man/start-cli/start-cli-tunnel-device-remove.1 create mode 100644 core/man/start-cli/start-cli-tunnel-device-show-config.1 create mode 100644 core/man/start-cli/start-cli-tunnel-device.1 create mode 100644 core/man/start-cli/start-cli-tunnel-port-forward-add.1 create mode 100644 core/man/start-cli/start-cli-tunnel-port-forward-remove.1 create mode 100644 core/man/start-cli/start-cli-tunnel-port-forward-set-enabled.1 create mode 100644 core/man/start-cli/start-cli-tunnel-port-forward-update-label.1 create mode 100644 core/man/start-cli/start-cli-tunnel-port-forward.1 create mode 100644 core/man/start-cli/start-cli-tunnel-restart.1 create mode 100644 core/man/start-cli/start-cli-tunnel-subnet-add.1 create mode 100644 core/man/start-cli/start-cli-tunnel-subnet-remove.1 create mode 100644 core/man/start-cli/start-cli-tunnel-subnet.1 create mode 100644 core/man/start-cli/start-cli-tunnel-update-apply.1 create mode 100644 core/man/start-cli/start-cli-tunnel-update-check.1 create mode 100644 core/man/start-cli/start-cli-tunnel-update.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-disable.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-enable.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-generate-certificate.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-get-available-ips.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-get-certificate.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-get-listen.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-import-certificate.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-init.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-set-listen.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web-uninit.1 create mode 100644 core/man/start-cli/start-cli-tunnel-web.1 create mode 100644 core/man/start-cli/start-cli-tunnel.1 create mode 100644 core/man/start-cli/start-cli-util-b3sum.1 create mode 100644 core/man/start-cli/start-cli-util.1 create mode 100644 core/man/start-cli/start-cli-wifi-add.1 create mode 100644 core/man/start-cli/start-cli-wifi-available-get.1 create mode 100644 core/man/start-cli/start-cli-wifi-available.1 create mode 100644 core/man/start-cli/start-cli-wifi-connect.1 create mode 100644 core/man/start-cli/start-cli-wifi-country-set.1 create mode 100644 core/man/start-cli/start-cli-wifi-country.1 create mode 100644 core/man/start-cli/start-cli-wifi-get.1 create mode 100644 core/man/start-cli/start-cli-wifi-remove.1 create mode 100644 core/man/start-cli/start-cli-wifi-set-enabled.1 create mode 100644 core/man/start-cli/start-cli-wifi.1 create mode 100644 core/man/start-cli/start-cli.1 create mode 100644 core/man/start-container/start-container-action-clear-tasks.1 create mode 100644 core/man/start-container/start-container-action-clear.1 create mode 100644 core/man/start-container/start-container-action-get-input.1 create mode 100644 core/man/start-container/start-container-action-run.1 create mode 100644 core/man/start-container/start-container-action.1 create mode 100644 core/man/start-container/start-container-check-dependencies.1 create mode 100644 core/man/start-container/start-container-echo.1 create mode 100644 core/man/start-container/start-container-get-data-version.1 create mode 100644 core/man/start-container/start-container-get-dependencies.1 create mode 100644 core/man/start-container/start-container-get-os-ip.1 create mode 100644 core/man/start-container/start-container-get-status.1 create mode 100644 core/man/start-container/start-container-git-info.1 create mode 100644 core/man/start-container/start-container-plugin-url.1 create mode 100644 core/man/start-container/start-container-plugin.1 create mode 100644 core/man/start-container/start-container-rebuild.1 create mode 100644 core/man/start-container/start-container-restart.1 create mode 100644 core/man/start-container/start-container-set-data-version.1 create mode 100644 core/man/start-container/start-container-set-dependencies.1 create mode 100644 core/man/start-container/start-container-set-main-status.1 create mode 100644 core/man/start-container/start-container-shutdown.1 create mode 100644 core/man/start-container/start-container-subcontainer-create-fs.1 create mode 100644 core/man/start-container/start-container-subcontainer-destroy-fs.1 create mode 100644 core/man/start-container/start-container-subcontainer-exec-command.1 create mode 100644 core/man/start-container/start-container-subcontainer-exec.1 create mode 100644 core/man/start-container/start-container-subcontainer-launch-init.1 create mode 100644 core/man/start-container/start-container-subcontainer-launch.1 create mode 100644 core/man/start-container/start-container-subcontainer.1 create mode 100644 core/man/start-container/start-container.1 create mode 100644 core/man/start-registry/start-registry-admin-add.1 create mode 100644 core/man/start-registry/start-registry-admin-list.1 create mode 100644 core/man/start-registry/start-registry-admin-remove.1 create mode 100644 core/man/start-registry/start-registry-admin-signer-add.1 create mode 100644 core/man/start-registry/start-registry-admin-signer-edit.1 create mode 100644 core/man/start-registry/start-registry-admin-signer-list.1 create mode 100644 core/man/start-registry/start-registry-admin-signer.1 create mode 100644 core/man/start-registry/start-registry-admin.1 create mode 100644 core/man/start-registry/start-registry-db-apply.1 create mode 100644 core/man/start-registry/start-registry-db-dump.1 create mode 100644 core/man/start-registry/start-registry-db.1 create mode 100644 core/man/start-registry/start-registry-index.1 create mode 100644 core/man/start-registry/start-registry-info-set-icon.1 create mode 100644 core/man/start-registry/start-registry-info-set-name.1 create mode 100644 core/man/start-registry/start-registry-info.1 create mode 100644 core/man/start-registry/start-registry-os-asset-add.1 create mode 100644 core/man/start-registry/start-registry-os-asset-get-img.1 create mode 100644 core/man/start-registry/start-registry-os-asset-get-iso.1 create mode 100644 core/man/start-registry/start-registry-os-asset-get-squashfs.1 create mode 100644 core/man/start-registry/start-registry-os-asset-get.1 create mode 100644 core/man/start-registry/start-registry-os-asset-remove.1 create mode 100644 core/man/start-registry/start-registry-os-asset-sign.1 create mode 100644 core/man/start-registry/start-registry-os-asset.1 create mode 100644 core/man/start-registry/start-registry-os-index.1 create mode 100644 core/man/start-registry/start-registry-os-version-add.1 create mode 100644 core/man/start-registry/start-registry-os-version-get.1 create mode 100644 core/man/start-registry/start-registry-os-version-remove.1 create mode 100644 core/man/start-registry/start-registry-os-version-signer-add.1 create mode 100644 core/man/start-registry/start-registry-os-version-signer-list.1 create mode 100644 core/man/start-registry/start-registry-os-version-signer-remove.1 create mode 100644 core/man/start-registry/start-registry-os-version-signer.1 create mode 100644 core/man/start-registry/start-registry-os-version.1 create mode 100644 core/man/start-registry/start-registry-os.1 create mode 100644 core/man/start-registry/start-registry-package-add-mirror.1 create mode 100644 core/man/start-registry/start-registry-package-add.1 create mode 100644 core/man/start-registry/start-registry-package-category-add-package.1 create mode 100644 core/man/start-registry/start-registry-package-category-add.1 create mode 100644 core/man/start-registry/start-registry-package-category-list.1 create mode 100644 core/man/start-registry/start-registry-package-category-remove-package.1 create mode 100644 core/man/start-registry/start-registry-package-category-remove.1 create mode 100644 core/man/start-registry/start-registry-package-category.1 create mode 100644 core/man/start-registry/start-registry-package-download.1 create mode 100644 core/man/start-registry/start-registry-package-get.1 create mode 100644 core/man/start-registry/start-registry-package-index.1 create mode 100644 core/man/start-registry/start-registry-package-remove-mirror.1 create mode 100644 core/man/start-registry/start-registry-package-remove.1 create mode 100644 core/man/start-registry/start-registry-package-signer-add.1 create mode 100644 core/man/start-registry/start-registry-package-signer-list.1 create mode 100644 core/man/start-registry/start-registry-package-signer-remove.1 create mode 100644 core/man/start-registry/start-registry-package-signer.1 create mode 100644 core/man/start-registry/start-registry-package.1 create mode 100644 core/man/start-registry/start-registry.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-get-pubkey.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-key-add.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-key-list.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-key-remove.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-key.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-login.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-logout.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-reset-password.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-session-kill.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-session-list.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-session.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth-set-password.1 create mode 100644 core/man/start-tunnel/start-tunnel-auth.1 create mode 100644 core/man/start-tunnel/start-tunnel-db-apply.1 create mode 100644 core/man/start-tunnel/start-tunnel-db-dump.1 create mode 100644 core/man/start-tunnel/start-tunnel-db.1 create mode 100644 core/man/start-tunnel/start-tunnel-device-add.1 create mode 100644 core/man/start-tunnel/start-tunnel-device-list.1 create mode 100644 core/man/start-tunnel/start-tunnel-device-remove.1 create mode 100644 core/man/start-tunnel/start-tunnel-device-show-config.1 create mode 100644 core/man/start-tunnel/start-tunnel-device.1 create mode 100644 core/man/start-tunnel/start-tunnel-port-forward-add.1 create mode 100644 core/man/start-tunnel/start-tunnel-port-forward-remove.1 create mode 100644 core/man/start-tunnel/start-tunnel-port-forward-set-enabled.1 create mode 100644 core/man/start-tunnel/start-tunnel-port-forward-update-label.1 create mode 100644 core/man/start-tunnel/start-tunnel-port-forward.1 create mode 100644 core/man/start-tunnel/start-tunnel-restart.1 create mode 100644 core/man/start-tunnel/start-tunnel-subnet-add.1 create mode 100644 core/man/start-tunnel/start-tunnel-subnet-remove.1 create mode 100644 core/man/start-tunnel/start-tunnel-subnet.1 create mode 100644 core/man/start-tunnel/start-tunnel-update-apply.1 create mode 100644 core/man/start-tunnel/start-tunnel-update-check.1 create mode 100644 core/man/start-tunnel/start-tunnel-update.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-disable.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-enable.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-generate-certificate.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-get-available-ips.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-get-certificate.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-get-listen.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-import-certificate.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-init.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-set-listen.1 create mode 100644 core/man/start-tunnel/start-tunnel-web-uninit.1 create mode 100644 core/man/start-tunnel/start-tunnel-web.1 create mode 100644 core/man/start-tunnel/start-tunnel.1 diff --git a/core/build/build-manpage.sh b/core/build/build-manpage.sh new file mode 100755 index 000000000..5adf74375 --- /dev/null +++ b/core/build/build-manpage.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +cd "$(dirname "${BASH_SOURCE[0]}")" + +source ./builder-alias.sh + +set -ea +shopt -s expand_aliases + +PROFILE=${PROFILE:-debug} +if [ "${PROFILE}" = "release" ]; then + BUILD_FLAGS="--release" +else + if [ "$PROFILE" != "debug" ]; then + >&2 echo "Unknown profile $PROFILE: falling back to debug..." + PROFILE=debug + fi +fi + +if [ -z "$ARCH" ]; then + ARCH=$(uname -m) +fi + +if [ "$ARCH" = "arm64" ]; then + ARCH="aarch64" +fi + +RUST_ARCH="$ARCH" +if [ "$ARCH" = "riscv64" ]; then + RUST_ARCH="riscv64gc" +fi + +cd ../.. +FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')" +RUSTFLAGS="" +if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then + RUSTFLAGS="--cfg tokio_unstable" +fi +echo "FEATURES=\"$FEATURES\"" +echo "RUSTFLAGS=\"$RUSTFLAGS\"" +rust-zig-builder cargo test --manifest-path=./core/Cargo.toml --lib $BUILD_FLAGS --features test,$FEATURES --locked 'export_manpage_' +if [ "$(ls -nd "core/man" | awk '{ print $3 }')" != "$UID" ]; then + rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID core/man && chown -R $UID:$UID /usr/local/cargo" +fi \ No newline at end of file diff --git a/core/man/start-cli/start-cli-auth-get-pubkey.1 b/core/man/start-cli/start-cli-auth-get-pubkey.1 new file mode 100644 index 000000000..703bb20ac --- /dev/null +++ b/core/man/start-cli/start-cli-auth-get-pubkey.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth-get-pubkey 1 "get-pubkey " +.SH NAME +start\-cli\-auth\-get\-pubkey \- Get the public key from the server +.SH SYNOPSIS +\fBstart\-cli auth get\-pubkey\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Get the public key from the server +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-auth-login.1 b/core/man/start-cli/start-cli-auth-login.1 new file mode 100644 index 000000000..127904b72 --- /dev/null +++ b/core/man/start-cli/start-cli-auth-login.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth-login 1 "login " +.SH NAME +start\-cli\-auth\-login \- Login to a new auth session +.SH SYNOPSIS +\fBstart\-cli auth login\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Login to a new auth session +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-auth-logout.1 b/core/man/start-cli/start-cli-auth-logout.1 new file mode 100644 index 000000000..905838ecf --- /dev/null +++ b/core/man/start-cli/start-cli-auth-logout.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth-logout 1 "logout " +.SH NAME +start\-cli\-auth\-logout \- Logout from current auth session +.SH SYNOPSIS +\fBstart\-cli auth logout\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISESSION\fR> +.SH DESCRIPTION +Logout from current auth session +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISESSION\fR> + diff --git a/core/man/start-cli/start-cli-auth-reset-password.1 b/core/man/start-cli/start-cli-auth-reset-password.1 new file mode 100644 index 000000000..147ab9ef7 --- /dev/null +++ b/core/man/start-cli/start-cli-auth-reset-password.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth-reset-password 1 "reset-password " +.SH NAME +start\-cli\-auth\-reset\-password \- Reset the password +.SH SYNOPSIS +\fBstart\-cli auth reset\-password\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Reset the password +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-auth-session-kill.1 b/core/man/start-cli/start-cli-auth-session-kill.1 new file mode 100644 index 000000000..accdd9055 --- /dev/null +++ b/core/man/start-cli/start-cli-auth-session-kill.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth-session-kill 1 "kill " +.SH NAME +start\-cli\-auth\-session\-kill \- Terminate auth sessions +.SH SYNOPSIS +\fBstart\-cli auth session kill\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIIDS\fR] +.SH DESCRIPTION +Terminate auth sessions +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIIDS\fR] +Session identifiers diff --git a/core/man/start-cli/start-cli-auth-session-list.1 b/core/man/start-cli/start-cli-auth-session-list.1 new file mode 100644 index 000000000..be54a0344 --- /dev/null +++ b/core/man/start-cli/start-cli-auth-session-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth-session-list 1 "list " +.SH NAME +start\-cli\-auth\-session\-list \- Display all auth sessions +.SH SYNOPSIS +\fBstart\-cli auth session list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display all auth sessions +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-auth-session.1 b/core/man/start-cli/start-cli-auth-session.1 new file mode 100644 index 000000000..7ca18ae60 --- /dev/null +++ b/core/man/start-cli/start-cli-auth-session.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth-session 1 "session " +.SH NAME +start\-cli\-auth\-session \- List or kill auth sessions +.SH SYNOPSIS +\fBstart\-cli auth session\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +List or kill auth sessions +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-auth\-session\-kill(1) +Terminate auth sessions +.TP +start\-cli\-auth\-session\-list(1) +Display all auth sessions diff --git a/core/man/start-cli/start-cli-auth.1 b/core/man/start-cli/start-cli-auth.1 new file mode 100644 index 000000000..e2283bd00 --- /dev/null +++ b/core/man/start-cli/start-cli-auth.1 @@ -0,0 +1,29 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-auth 1 "auth " +.SH NAME +start\-cli\-auth \- Commands related to Authentication i.e. login, logout +.SH SYNOPSIS +\fBstart\-cli auth\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to Authentication i.e. login, logout +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-auth\-get\-pubkey(1) +Get the public key from the server +.TP +start\-cli\-auth\-login(1) +Login to a new auth session +.TP +start\-cli\-auth\-logout(1) +Logout from current auth session +.TP +start\-cli\-auth\-reset\-password(1) +Reset the password +.TP +start\-cli\-auth\-session(1) +List or kill auth sessions diff --git a/core/man/start-cli/start-cli-backup-create.1 b/core/man/start-cli/start-cli-backup-create.1 new file mode 100644 index 000000000..f43e3ce4a --- /dev/null +++ b/core/man/start-cli/start-cli-backup-create.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-create 1 "create " +.SH NAME +start\-cli\-backup\-create \- Create a backup for all packages +.SH SYNOPSIS +\fBstart\-cli backup create\fR [\fB\-\-old\-password\fR] [\fB\-\-package\-ids\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fITARGET_ID\fR> <\fIPASSWORD\fR> +.SH DESCRIPTION +Create a backup for all packages +.SH OPTIONS +.TP +\fB\-\-old\-password\fR \fI\fR +Previous backup password +.TP +\fB\-\-package\-ids\fR \fI\fR +Package IDs to include in backup +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fITARGET_ID\fR> +Backup target identifier +.TP +<\fIPASSWORD\fR> +Password for backup encryption diff --git a/core/man/start-cli/start-cli-backup-target-cifs-add.1 b/core/man/start-cli/start-cli-backup-target-cifs-add.1 new file mode 100644 index 000000000..4e20c033b --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-cifs-add.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-cifs-add 1 "add " +.SH NAME +start\-cli\-backup\-target\-cifs\-add \- Add a new backup target +.SH SYNOPSIS +\fBstart\-cli backup target cifs add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIHOSTNAME\fR> <\fIPATH\fR> <\fIUSERNAME\fR> [\fIPASSWORD\fR] +.SH DESCRIPTION +Add a new backup target +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIHOSTNAME\fR> +CIFS server hostname +.TP +<\fIPATH\fR> +Path on the CIFS share +.TP +<\fIUSERNAME\fR> +CIFS authentication username +.TP +[\fIPASSWORD\fR] +CIFS authentication password diff --git a/core/man/start-cli/start-cli-backup-target-cifs-remove.1 b/core/man/start-cli/start-cli-backup-target-cifs-remove.1 new file mode 100644 index 000000000..8dab94a3c --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-cifs-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-cifs-remove 1 "remove " +.SH NAME +start\-cli\-backup\-target\-cifs\-remove \- Remove existing backup target +.SH SYNOPSIS +\fBstart\-cli backup target cifs remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Remove existing backup target +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Backup target identifier diff --git a/core/man/start-cli/start-cli-backup-target-cifs-update.1 b/core/man/start-cli/start-cli-backup-target-cifs-update.1 new file mode 100644 index 000000000..a8721bda5 --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-cifs-update.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-cifs-update 1 "update " +.SH NAME +start\-cli\-backup\-target\-cifs\-update \- Update an existing backup target +.SH SYNOPSIS +\fBstart\-cli backup target cifs update\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fIHOSTNAME\fR> <\fIPATH\fR> <\fIUSERNAME\fR> [\fIPASSWORD\fR] +.SH DESCRIPTION +Update an existing backup target +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Backup target identifier +.TP +<\fIHOSTNAME\fR> +CIFS server hostname +.TP +<\fIPATH\fR> +Path on the CIFS share +.TP +<\fIUSERNAME\fR> +CIFS authentication username +.TP +[\fIPASSWORD\fR] +CIFS authentication password diff --git a/core/man/start-cli/start-cli-backup-target-cifs.1 b/core/man/start-cli/start-cli-backup-target-cifs.1 new file mode 100644 index 000000000..e7afdc199 --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-cifs.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-cifs 1 "cifs " +.SH NAME +start\-cli\-backup\-target\-cifs \- Add, remove, or update a backup target +.SH SYNOPSIS +\fBstart\-cli backup target cifs\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Add, remove, or update a backup target +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-backup\-target\-cifs\-add(1) +Add a new backup target +.TP +start\-cli\-backup\-target\-cifs\-remove(1) +Remove existing backup target +.TP +start\-cli\-backup\-target\-cifs\-update(1) +Update an existing backup target diff --git a/core/man/start-cli/start-cli-backup-target-info.1 b/core/man/start-cli/start-cli-backup-target-info.1 new file mode 100644 index 000000000..c1ff66f11 --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-info.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-info 1 "info " +.SH NAME +start\-cli\-backup\-target\-info \- Display backup information for a package +.SH SYNOPSIS +\fBstart\-cli backup target info\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fITARGET_ID\fR> <\fISERVER_ID\fR> <\fIPASSWORD\fR> +.SH DESCRIPTION +Display backup information for a package +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fITARGET_ID\fR> +Backup target identifier +.TP +<\fISERVER_ID\fR> +Unique server identifier +.TP +<\fIPASSWORD\fR> +Password for backup encryption diff --git a/core/man/start-cli/start-cli-backup-target-list.1 b/core/man/start-cli/start-cli-backup-target-list.1 new file mode 100644 index 000000000..49886b84d --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-list 1 "list " +.SH NAME +start\-cli\-backup\-target\-list \- List existing backup targets +.SH SYNOPSIS +\fBstart\-cli backup target list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List existing backup targets +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-backup-target-mount.1 b/core/man/start-cli/start-cli-backup-target-mount.1 new file mode 100644 index 000000000..caf558310 --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-mount.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-mount 1 "mount " +.SH NAME +start\-cli\-backup\-target\-mount \- Mount a backup target +.SH SYNOPSIS +\fBstart\-cli backup target mount\fR [\fB\-\-server\-id\fR] [\fB\-\-allow\-partial\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fITARGET_ID\fR> <\fIPASSWORD\fR> +.SH DESCRIPTION +Mount a backup target +.SH OPTIONS +.TP +\fB\-\-server\-id\fR \fI\fR +Unique server identifier +.TP +\fB\-\-allow\-partial\fR +Leave media mounted even if backupfs fails to mount +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fITARGET_ID\fR> +Backup target identifier +.TP +<\fIPASSWORD\fR> +Password for backup encryption diff --git a/core/man/start-cli/start-cli-backup-target-umount.1 b/core/man/start-cli/start-cli-backup-target-umount.1 new file mode 100644 index 000000000..5b8bb75ef --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target-umount.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target-umount 1 "umount " +.SH NAME +start\-cli\-backup\-target\-umount \- Unmount a backup target +.SH SYNOPSIS +\fBstart\-cli backup target umount\fR [\fB\-h\fR|\fB\-\-help\fR] [\fITARGET_ID\fR] +.SH DESCRIPTION +Unmount a backup target +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fITARGET_ID\fR] +Backup target identifier diff --git a/core/man/start-cli/start-cli-backup-target.1 b/core/man/start-cli/start-cli-backup-target.1 new file mode 100644 index 000000000..82d1de933 --- /dev/null +++ b/core/man/start-cli/start-cli-backup-target.1 @@ -0,0 +1,29 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup-target 1 "target " +.SH NAME +start\-cli\-backup\-target \- Commands related to a backup target +.SH SYNOPSIS +\fBstart\-cli backup target\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to a backup target +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-backup\-target\-cifs(1) +Add, remove, or update a backup target +.TP +start\-cli\-backup\-target\-info(1) +Display backup information for a package +.TP +start\-cli\-backup\-target\-list(1) +List existing backup targets +.TP +start\-cli\-backup\-target\-mount(1) +Mount a backup target +.TP +start\-cli\-backup\-target\-umount(1) +Unmount a backup target diff --git a/core/man/start-cli/start-cli-backup.1 b/core/man/start-cli/start-cli-backup.1 new file mode 100644 index 000000000..5e60d0432 --- /dev/null +++ b/core/man/start-cli/start-cli-backup.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-backup 1 "backup " +.SH NAME +start\-cli\-backup \- Commands related to backup creation and backup targets +.SH SYNOPSIS +\fBstart\-cli backup\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to backup creation and backup targets +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-backup\-create(1) +Create a backup for all packages +.TP +start\-cli\-backup\-target(1) +Commands related to a backup target diff --git a/core/man/start-cli/start-cli-db-apply.1 b/core/man/start-cli/start-cli-db-apply.1 new file mode 100644 index 000000000..f88966143 --- /dev/null +++ b/core/man/start-cli/start-cli-db-apply.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-db-apply 1 "apply " +.SH NAME +start\-cli\-db\-apply \- Update a database record +.SH SYNOPSIS +\fBstart\-cli db apply\fR [\fB\-\-allow\-model\-mismatch\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIEXPR\fR> [\fIPATH\fR] +.SH DESCRIPTION +Update a database record +.SH OPTIONS +.TP +\fB\-\-allow\-model\-mismatch\fR +Allow database model mismatch +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIEXPR\fR> +Database patch expression to apply +.TP +[\fIPATH\fR] +Path to the database diff --git a/core/man/start-cli/start-cli-db-dump.1 b/core/man/start-cli/start-cli-db-dump.1 new file mode 100644 index 000000000..d8c55918d --- /dev/null +++ b/core/man/start-cli/start-cli-db-dump.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-db-dump 1 "dump " +.SH NAME +start\-cli\-db\-dump \- Filter and query the database +.SH SYNOPSIS +\fBstart\-cli db dump\fR [\fB\-p\fR|\fB\-\-include\-private\fR] [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIPATH\fR] +.SH DESCRIPTION +Filter and query the database +.SH OPTIONS +.TP +\fB\-p\fR, \fB\-\-include\-private\fR +Include private data in output +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIPATH\fR] +Path to the database diff --git a/core/man/start-cli/start-cli-db-put-ui.1 b/core/man/start-cli/start-cli-db-put-ui.1 new file mode 100644 index 000000000..5b3587f17 --- /dev/null +++ b/core/man/start-cli/start-cli-db-put-ui.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-db-put-ui 1 "ui " +.SH NAME +start\-cli\-db\-put\-ui \- Add path and value to db +.SH SYNOPSIS +\fBstart\-cli db put ui\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIPOINTER\fR> <\fIVALUE\fR> +.SH DESCRIPTION +Add path and value to db +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIPOINTER\fR> +JSON pointer to specific value +.TP +<\fIVALUE\fR> +JSON value to set diff --git a/core/man/start-cli/start-cli-db-put.1 b/core/man/start-cli/start-cli-db-put.1 new file mode 100644 index 000000000..a087f07aa --- /dev/null +++ b/core/man/start-cli/start-cli-db-put.1 @@ -0,0 +1,17 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-db-put 1 "put " +.SH NAME +start\-cli\-db\-put \- Command for adding UI record to db +.SH SYNOPSIS +\fBstart\-cli db put\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Command for adding UI record to db +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-db\-put\-ui(1) +Add path and value to db diff --git a/core/man/start-cli/start-cli-db.1 b/core/man/start-cli/start-cli-db.1 new file mode 100644 index 000000000..cace8f21c --- /dev/null +++ b/core/man/start-cli/start-cli-db.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-db 1 "db " +.SH NAME +start\-cli\-db \- Commands to interact with the db i.e. dump, put, apply +.SH SYNOPSIS +\fBstart\-cli db\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to interact with the db i.e. dump, put, apply +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-db\-apply(1) +Update a database record +.TP +start\-cli\-db\-dump(1) +Filter and query the database +.TP +start\-cli\-db\-put(1) +Command for adding UI record to db diff --git a/core/man/start-cli/start-cli-diagnostic-disk-forget.1 b/core/man/start-cli/start-cli-diagnostic-disk-forget.1 new file mode 100644 index 000000000..71f864d8e --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-disk-forget.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-disk-forget 1 "forget " +.SH NAME +start\-cli\-diagnostic\-disk\-forget \- Remove disk filesystem +.SH SYNOPSIS +\fBstart\-cli diagnostic disk forget\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Remove disk filesystem +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-diagnostic-disk-repair.1 b/core/man/start-cli/start-cli-diagnostic-disk-repair.1 new file mode 100644 index 000000000..d2ef7c301 --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-disk-repair.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-disk-repair 1 "repair " +.SH NAME +start\-cli\-diagnostic\-disk\-repair \- Repair disk corruption +.SH SYNOPSIS +\fBstart\-cli diagnostic disk repair\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Repair disk corruption +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-diagnostic-disk.1 b/core/man/start-cli/start-cli-diagnostic-disk.1 new file mode 100644 index 000000000..e92a503f6 --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-disk.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-disk 1 "disk " +.SH NAME +start\-cli\-diagnostic\-disk \- Command to remove disk from filesystem +.SH SYNOPSIS +\fBstart\-cli diagnostic disk\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Command to remove disk from filesystem +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-diagnostic\-disk\-forget(1) +Remove disk filesystem +.TP +start\-cli\-diagnostic\-disk\-repair(1) +Repair disk corruption diff --git a/core/man/start-cli/start-cli-diagnostic-error.1 b/core/man/start-cli/start-cli-diagnostic-error.1 new file mode 100644 index 000000000..8435f72fd --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-error.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-error 1 "error " +.SH NAME +start\-cli\-diagnostic\-error \- Display diagnostic error +.SH SYNOPSIS +\fBstart\-cli diagnostic error\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display diagnostic error +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-diagnostic-kernel-logs.1 b/core/man/start-cli/start-cli-diagnostic-kernel-logs.1 new file mode 100644 index 000000000..0d1502109 --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-kernel-logs.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-kernel-logs 1 "kernel-logs " +.SH NAME +start\-cli\-diagnostic\-kernel\-logs \- Display kernel logs +.SH SYNOPSIS +\fBstart\-cli diagnostic kernel\-logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display kernel logs +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-diagnostic-logs.1 b/core/man/start-cli/start-cli-diagnostic-logs.1 new file mode 100644 index 000000000..dc3aeb4b8 --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-logs.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-logs 1 "logs " +.SH NAME +start\-cli\-diagnostic\-logs \- Display OS logs +.SH SYNOPSIS +\fBstart\-cli diagnostic logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display OS logs +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-diagnostic-rebuild.1 b/core/man/start-cli/start-cli-diagnostic-rebuild.1 new file mode 100644 index 000000000..7397e3844 --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-rebuild.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-rebuild 1 "rebuild " +.SH NAME +start\-cli\-diagnostic\-rebuild \- Teardown and rebuild containers +.SH SYNOPSIS +\fBstart\-cli diagnostic rebuild\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Teardown and rebuild containers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-diagnostic-restart.1 b/core/man/start-cli/start-cli-diagnostic-restart.1 new file mode 100644 index 000000000..f8677c9c1 --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic-restart.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic-restart 1 "restart " +.SH NAME +start\-cli\-diagnostic\-restart \- Restart the server +.SH SYNOPSIS +\fBstart\-cli diagnostic restart\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Restart the server +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-diagnostic.1 b/core/man/start-cli/start-cli-diagnostic.1 new file mode 100644 index 000000000..d8b4003f7 --- /dev/null +++ b/core/man/start-cli/start-cli-diagnostic.1 @@ -0,0 +1,32 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-diagnostic 1 "diagnostic " +.SH NAME +start\-cli\-diagnostic \- Commands to display logs, restart the server, etc +.SH SYNOPSIS +\fBstart\-cli diagnostic\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to display logs, restart the server, etc +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-diagnostic\-disk(1) +Command to remove disk from filesystem +.TP +start\-cli\-diagnostic\-error(1) +Display diagnostic error +.TP +start\-cli\-diagnostic\-kernel\-logs(1) +Display kernel logs +.TP +start\-cli\-diagnostic\-logs(1) +Display OS logs +.TP +start\-cli\-diagnostic\-rebuild(1) +Teardown and rebuild containers +.TP +start\-cli\-diagnostic\-restart(1) +Restart the server diff --git a/core/man/start-cli/start-cli-disk-list.1 b/core/man/start-cli/start-cli-disk-list.1 new file mode 100644 index 000000000..497fc21d2 --- /dev/null +++ b/core/man/start-cli/start-cli-disk-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-disk-list 1 "list " +.SH NAME +start\-cli\-disk\-list \- List disk information +.SH SYNOPSIS +\fBstart\-cli disk list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List disk information +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-disk-repair.1 b/core/man/start-cli/start-cli-disk-repair.1 new file mode 100644 index 000000000..3de37a206 --- /dev/null +++ b/core/man/start-cli/start-cli-disk-repair.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-disk-repair 1 "repair " +.SH NAME +start\-cli\-disk\-repair \- Repair disk corruption +.SH SYNOPSIS +\fBstart\-cli disk repair\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Repair disk corruption +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-disk.1 b/core/man/start-cli/start-cli-disk.1 new file mode 100644 index 000000000..772eded99 --- /dev/null +++ b/core/man/start-cli/start-cli-disk.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-disk 1 "disk " +.SH NAME +start\-cli\-disk \- Commands for listing disk info and repairing +.SH SYNOPSIS +\fBstart\-cli disk\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands for listing disk info and repairing +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-disk\-list(1) +List disk information +.TP +start\-cli\-disk\-repair(1) +Repair disk corruption diff --git a/core/man/start-cli/start-cli-echo.1 b/core/man/start-cli/start-cli-echo.1 new file mode 100644 index 000000000..2a2849597 --- /dev/null +++ b/core/man/start-cli/start-cli-echo.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-echo 1 "echo " +.SH NAME +start\-cli\-echo \- Echo a message back +.SH SYNOPSIS +\fBstart\-cli echo\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIMESSAGE\fR> +.SH DESCRIPTION +Echo a message back +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIMESSAGE\fR> +Message to echo back diff --git a/core/man/start-cli/start-cli-flash-os.1 b/core/man/start-cli/start-cli-flash-os.1 new file mode 100644 index 000000000..35c1c9f20 --- /dev/null +++ b/core/man/start-cli/start-cli-flash-os.1 @@ -0,0 +1,32 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-flash-os 1 "flash-os " +.SH NAME +start\-cli\-flash\-os \- Flash StartOS to a drive +.SH SYNOPSIS +\fBstart\-cli flash\-os\fR [\fB\-\-efi\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fISQUASHFS\fR> <\fIDISK\fR> +.SH DESCRIPTION +Flash StartOS to a drive +.SH OPTIONS +.TP +\fB\-\-efi\fR \fI\fR +Use EFI boot mode +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +true +.IP \(bu 2 +false +.RE +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISQUASHFS\fR> +Path to squashfs image file +.TP +<\fIDISK\fR> +Target disk for installation diff --git a/core/man/start-cli/start-cli-git-info.1 b/core/man/start-cli/start-cli-git-info.1 new file mode 100644 index 000000000..aabf46dae --- /dev/null +++ b/core/man/start-cli/start-cli-git-info.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-git-info 1 "git-info " +.SH NAME +start\-cli\-git\-info \- Display the git hash of this build +.SH SYNOPSIS +\fBstart\-cli git\-info\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display the git hash of this build +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-init-kernel-logs.1 b/core/man/start-cli/start-cli-init-kernel-logs.1 new file mode 100644 index 000000000..475f95470 --- /dev/null +++ b/core/man/start-cli/start-cli-init-kernel-logs.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-init-kernel-logs 1 "kernel-logs " +.SH NAME +start\-cli\-init\-kernel\-logs \- Display kernel logs +.SH SYNOPSIS +\fBstart\-cli init kernel\-logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display kernel logs +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-init-key.1 b/core/man/start-cli/start-cli-init-key.1 new file mode 100644 index 000000000..62e21e874 --- /dev/null +++ b/core/man/start-cli/start-cli-init-key.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-init-key 1 "init-key " +.SH NAME +start\-cli\-init\-key \- Create a new developer key +.SH SYNOPSIS +\fBstart\-cli init\-key\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Create a new developer key +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-init-logs.1 b/core/man/start-cli/start-cli-init-logs.1 new file mode 100644 index 000000000..9e778406b --- /dev/null +++ b/core/man/start-cli/start-cli-init-logs.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-init-logs 1 "logs " +.SH NAME +start\-cli\-init\-logs \- Display OS logs +.SH SYNOPSIS +\fBstart\-cli init logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display OS logs +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-init-subscribe.1 b/core/man/start-cli/start-cli-init-subscribe.1 new file mode 100644 index 000000000..375e13c76 --- /dev/null +++ b/core/man/start-cli/start-cli-init-subscribe.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-init-subscribe 1 "subscribe " +.SH NAME +start\-cli\-init\-subscribe \- Get initialization progress +.SH SYNOPSIS +\fBstart\-cli init subscribe\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Get initialization progress +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-init.1 b/core/man/start-cli/start-cli-init.1 new file mode 100644 index 000000000..9b05b8f2f --- /dev/null +++ b/core/man/start-cli/start-cli-init.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-init 1 "init " +.SH NAME +start\-cli\-init \- Commands for initialization +.SH SYNOPSIS +\fBstart\-cli init\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands for initialization +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-init\-kernel\-logs(1) +Display kernel logs +.TP +start\-cli\-init\-logs(1) +Display OS logs +.TP +start\-cli\-init\-subscribe(1) +Get initialization progress diff --git a/core/man/start-cli/start-cli-kiosk-disable.1 b/core/man/start-cli/start-cli-kiosk-disable.1 new file mode 100644 index 000000000..9d58d9523 --- /dev/null +++ b/core/man/start-cli/start-cli-kiosk-disable.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-kiosk-disable 1 "disable " +.SH NAME +start\-cli\-kiosk\-disable \- Disable kiosk mode +.SH SYNOPSIS +\fBstart\-cli kiosk disable\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Disable kiosk mode +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-kiosk-enable.1 b/core/man/start-cli/start-cli-kiosk-enable.1 new file mode 100644 index 000000000..4a49e0d15 --- /dev/null +++ b/core/man/start-cli/start-cli-kiosk-enable.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-kiosk-enable 1 "enable " +.SH NAME +start\-cli\-kiosk\-enable \- Enable kiosk mode +.SH SYNOPSIS +\fBstart\-cli kiosk enable\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Enable kiosk mode +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-kiosk.1 b/core/man/start-cli/start-cli-kiosk.1 new file mode 100644 index 000000000..82fd3ac7c --- /dev/null +++ b/core/man/start-cli/start-cli-kiosk.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-kiosk 1 "kiosk " +.SH NAME +start\-cli\-kiosk \- Commands for kiosk mode +.SH SYNOPSIS +\fBstart\-cli kiosk\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands for kiosk mode +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-kiosk\-disable(1) +Disable kiosk mode +.TP +start\-cli\-kiosk\-enable(1) +Enable kiosk mode diff --git a/core/man/start-cli/start-cli-net-acme-init.1 b/core/man/start-cli/start-cli-net-acme-init.1 new file mode 100644 index 000000000..44963263d --- /dev/null +++ b/core/man/start-cli/start-cli-net-acme-init.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-acme-init 1 "init " +.SH NAME +start\-cli\-net\-acme\-init \- Setup ACME certificate acquisition +.SH SYNOPSIS +\fBstart\-cli net acme init\fR <\fB\-\-provider\fR> [\fB\-\-contact\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Setup ACME certificate acquisition +.SH OPTIONS +.TP +\fB\-\-provider\fR \fI\fR +ACME provider identifier or url +.TP +\fB\-\-contact\fR \fI\fR +Contact email for ACME certificate authority +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-acme-remove.1 b/core/man/start-cli/start-cli-net-acme-remove.1 new file mode 100644 index 000000000..0dcfca138 --- /dev/null +++ b/core/man/start-cli/start-cli-net-acme-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-acme-remove 1 "remove " +.SH NAME +start\-cli\-net\-acme\-remove \- Remove ACME certificate acquisition configuration +.SH SYNOPSIS +\fBstart\-cli net acme remove\fR <\fB\-\-provider\fR> [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Remove ACME certificate acquisition configuration +.SH OPTIONS +.TP +\fB\-\-provider\fR \fI\fR +ACME provider identifier or url +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-acme.1 b/core/man/start-cli/start-cli-net-acme.1 new file mode 100644 index 000000000..f1a95d1cb --- /dev/null +++ b/core/man/start-cli/start-cli-net-acme.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-acme 1 "acme " +.SH NAME +start\-cli\-net\-acme \- Setup ACME certificate +.SH SYNOPSIS +\fBstart\-cli net acme\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Setup ACME certificate +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-net\-acme\-init(1) +Setup ACME certificate acquisition +.TP +start\-cli\-net\-acme\-remove(1) +Remove ACME certificate acquisition configuration diff --git a/core/man/start-cli/start-cli-net-dns-dump-table.1 b/core/man/start-cli/start-cli-net-dns-dump-table.1 new file mode 100644 index 000000000..94b524131 --- /dev/null +++ b/core/man/start-cli/start-cli-net-dns-dump-table.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-dns-dump-table 1 "dump-table " +.SH NAME +start\-cli\-net\-dns\-dump\-table \- Dump address resolution table +.SH SYNOPSIS +\fBstart\-cli net dns dump\-table\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Dump address resolution table +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-dns-query.1 b/core/man/start-cli/start-cli-net-dns-query.1 new file mode 100644 index 000000000..410cc5330 --- /dev/null +++ b/core/man/start-cli/start-cli-net-dns-query.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-dns-query 1 "query " +.SH NAME +start\-cli\-net\-dns\-query \- Test DNS configuration for a domain +.SH SYNOPSIS +\fBstart\-cli net dns query\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> +.SH DESCRIPTION +Test DNS configuration for a domain +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name diff --git a/core/man/start-cli/start-cli-net-dns-set-static.1 b/core/man/start-cli/start-cli-net-dns-set-static.1 new file mode 100644 index 000000000..766e921a8 --- /dev/null +++ b/core/man/start-cli/start-cli-net-dns-set-static.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-dns-set-static 1 "set-static " +.SH NAME +start\-cli\-net\-dns\-set\-static \- Set static DNS servers +.SH SYNOPSIS +\fBstart\-cli net dns set\-static\fR [\fB\-h\fR|\fB\-\-help\fR] [\fISERVERS\fR] +.SH DESCRIPTION +Set static DNS servers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fISERVERS\fR] +DNS servers to use diff --git a/core/man/start-cli/start-cli-net-dns.1 b/core/man/start-cli/start-cli-net-dns.1 new file mode 100644 index 000000000..c3c545460 --- /dev/null +++ b/core/man/start-cli/start-cli-net-dns.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-dns 1 "dns " +.SH NAME +start\-cli\-net\-dns \- Manage and query DNS +.SH SYNOPSIS +\fBstart\-cli net dns\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Manage and query DNS +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-net\-dns\-dump\-table(1) +Dump address resolution table +.TP +start\-cli\-net\-dns\-query(1) +Test DNS configuration for a domain +.TP +start\-cli\-net\-dns\-set\-static(1) +Set static DNS servers diff --git a/core/man/start-cli/start-cli-net-forward-dump-table.1 b/core/man/start-cli/start-cli-net-forward-dump-table.1 new file mode 100644 index 000000000..79e4e01e5 --- /dev/null +++ b/core/man/start-cli/start-cli-net-forward-dump-table.1 @@ -0,0 +1,15 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-forward-dump-table 1 "dump-table " +.SH NAME +start\-cli\-net\-forward\-dump\-table +.SH SYNOPSIS +\fBstart\-cli net forward dump\-table\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-forward.1 b/core/man/start-cli/start-cli-net-forward.1 new file mode 100644 index 000000000..6e2108602 --- /dev/null +++ b/core/man/start-cli/start-cli-net-forward.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-forward 1 "forward " +.SH NAME +start\-cli\-net\-forward \- Manage port forwards +.SH SYNOPSIS +\fBstart\-cli net forward\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Manage port forwards +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-net\-forward\-dump\-table(1) diff --git a/core/man/start-cli/start-cli-net-gateway-check-dns.1 b/core/man/start-cli/start-cli-net-gateway-check-dns.1 new file mode 100644 index 000000000..6eab6c125 --- /dev/null +++ b/core/man/start-cli/start-cli-net-gateway-check-dns.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-gateway-check-dns 1 "check-dns " +.SH NAME +start\-cli\-net\-gateway\-check\-dns \- Check DNS configuration for a gateway +.SH SYNOPSIS +\fBstart\-cli net gateway check\-dns\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIGATEWAY\fR> +.SH DESCRIPTION +Check DNS configuration for a gateway +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIGATEWAY\fR> +Gateway identifier diff --git a/core/man/start-cli/start-cli-net-gateway-check-port.1 b/core/man/start-cli/start-cli-net-gateway-check-port.1 new file mode 100644 index 000000000..4ee5d6665 --- /dev/null +++ b/core/man/start-cli/start-cli-net-gateway-check-port.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-gateway-check-port 1 "check-port " +.SH NAME +start\-cli\-net\-gateway\-check\-port \- about.check\-port\-reachability +.SH SYNOPSIS +\fBstart\-cli net gateway check\-port\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIPORT\fR> <\fIGATEWAY\fR> +.SH DESCRIPTION +about.check\-port\-reachability +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIPORT\fR> +help.arg.port +.TP +<\fIGATEWAY\fR> +Gateway identifier diff --git a/core/man/start-cli/start-cli-net-gateway-forget.1 b/core/man/start-cli/start-cli-net-gateway-forget.1 new file mode 100644 index 000000000..9896062f8 --- /dev/null +++ b/core/man/start-cli/start-cli-net-gateway-forget.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-gateway-forget 1 "forget " +.SH NAME +start\-cli\-net\-gateway\-forget \- Forget a disconnected gateway +.SH SYNOPSIS +\fBstart\-cli net gateway forget\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIGATEWAY\fR> +.SH DESCRIPTION +Forget a disconnected gateway +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIGATEWAY\fR> +Gateway identifier diff --git a/core/man/start-cli/start-cli-net-gateway-list.1 b/core/man/start-cli/start-cli-net-gateway-list.1 new file mode 100644 index 000000000..416ec3365 --- /dev/null +++ b/core/man/start-cli/start-cli-net-gateway-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-gateway-list 1 "list " +.SH NAME +start\-cli\-net\-gateway\-list \- Show gateways StartOS can listen on +.SH SYNOPSIS +\fBstart\-cli net gateway list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Show gateways StartOS can listen on +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-gateway-set-default-outbound.1 b/core/man/start-cli/start-cli-net-gateway-set-default-outbound.1 new file mode 100644 index 000000000..76ee6c7ce --- /dev/null +++ b/core/man/start-cli/start-cli-net-gateway-set-default-outbound.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-gateway-set-default-outbound 1 "set-default-outbound " +.SH NAME +start\-cli\-net\-gateway\-set\-default\-outbound \- about.set\-default\-outbound\-gateway +.SH SYNOPSIS +\fBstart\-cli net gateway set\-default\-outbound\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIGATEWAY\fR] +.SH DESCRIPTION +about.set\-default\-outbound\-gateway +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIGATEWAY\fR] +Gateway identifier diff --git a/core/man/start-cli/start-cli-net-gateway-set-name.1 b/core/man/start-cli/start-cli-net-gateway-set-name.1 new file mode 100644 index 000000000..b8ab927e2 --- /dev/null +++ b/core/man/start-cli/start-cli-net-gateway-set-name.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-gateway-set-name 1 "set-name " +.SH NAME +start\-cli\-net\-gateway\-set\-name \- Rename a gateway +.SH SYNOPSIS +\fBstart\-cli net gateway set\-name\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fINAME\fR> +.SH DESCRIPTION +Rename a gateway +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Gateway identifier +.TP +<\fINAME\fR> +Name of the gateway diff --git a/core/man/start-cli/start-cli-net-gateway.1 b/core/man/start-cli/start-cli-net-gateway.1 new file mode 100644 index 000000000..51741dc9c --- /dev/null +++ b/core/man/start-cli/start-cli-net-gateway.1 @@ -0,0 +1,32 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-gateway 1 "gateway " +.SH NAME +start\-cli\-net\-gateway \- View and edit gateway configurations +.SH SYNOPSIS +\fBstart\-cli net gateway\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +View and edit gateway configurations +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-net\-gateway\-check\-dns(1) +Check DNS configuration for a gateway +.TP +start\-cli\-net\-gateway\-check\-port(1) +about.check\-port\-reachability +.TP +start\-cli\-net\-gateway\-forget(1) +Forget a disconnected gateway +.TP +start\-cli\-net\-gateway\-list(1) +Show gateways StartOS can listen on +.TP +start\-cli\-net\-gateway\-set\-default\-outbound(1) +about.set\-default\-outbound\-gateway +.TP +start\-cli\-net\-gateway\-set\-name(1) +Rename a gateway diff --git a/core/man/start-cli/start-cli-net-tunnel-add.1 b/core/man/start-cli/start-cli-net-tunnel-add.1 new file mode 100644 index 000000000..d315b28ce --- /dev/null +++ b/core/man/start-cli/start-cli-net-tunnel-add.1 @@ -0,0 +1,35 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-tunnel-add 1 "add " +.SH NAME +start\-cli\-net\-tunnel\-add \- Add a new tunnel +.SH SYNOPSIS +\fBstart\-cli net tunnel add\fR [\fB\-\-set\-as\-default\-outbound\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fINAME\fR> <\fICONFIG\fR> [\fIGATEWAY_TYPE\fR] +.SH DESCRIPTION +Add a new tunnel +.SH OPTIONS +.TP +\fB\-\-set\-as\-default\-outbound\fR +help.arg.set\-as\-default\-outbound +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fINAME\fR> +Tunnel name +.TP +<\fICONFIG\fR> +WireGuard configuration +.TP +[\fIGATEWAY_TYPE\fR] +help.arg.gateway\-type +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +inbound\-outbound +.IP \(bu 2 +outbound\-only +.RE diff --git a/core/man/start-cli/start-cli-net-tunnel-remove.1 b/core/man/start-cli/start-cli-net-tunnel-remove.1 new file mode 100644 index 000000000..d8ba47885 --- /dev/null +++ b/core/man/start-cli/start-cli-net-tunnel-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-tunnel-remove 1 "remove " +.SH NAME +start\-cli\-net\-tunnel\-remove \- Remove a tunnel +.SH SYNOPSIS +\fBstart\-cli net tunnel remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Remove a tunnel +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Gateway identifier diff --git a/core/man/start-cli/start-cli-net-tunnel.1 b/core/man/start-cli/start-cli-net-tunnel.1 new file mode 100644 index 000000000..fa5afdead --- /dev/null +++ b/core/man/start-cli/start-cli-net-tunnel.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-tunnel 1 "tunnel " +.SH NAME +start\-cli\-net\-tunnel \- Manage tunnels +.SH SYNOPSIS +\fBstart\-cli net tunnel\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Manage tunnels +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-net\-tunnel\-add(1) +Add a new tunnel +.TP +start\-cli\-net\-tunnel\-remove(1) +Remove a tunnel diff --git a/core/man/start-cli/start-cli-net-vhost-add-passthrough.1 b/core/man/start-cli/start-cli-net-vhost-add-passthrough.1 new file mode 100644 index 000000000..9d6aa9892 --- /dev/null +++ b/core/man/start-cli/start-cli-net-vhost-add-passthrough.1 @@ -0,0 +1,27 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-vhost-add-passthrough 1 "add-passthrough " +.SH NAME +start\-cli\-net\-vhost\-add\-passthrough +.SH SYNOPSIS +\fBstart\-cli net vhost add\-passthrough\fR <\fB\-\-hostname\fR> <\fB\-\-listen\-port\fR> <\fB\-\-backend\fR> [\fB\-\-public\-gateway\fR] [\fB\-\-private\-ip\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-\-hostname\fR \fI\fR + +.TP +\fB\-\-listen\-port\fR \fI\fR + +.TP +\fB\-\-backend\fR \fI\fR + +.TP +\fB\-\-public\-gateway\fR \fI\fR + +.TP +\fB\-\-private\-ip\fR \fI\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-vhost-dump-table.1 b/core/man/start-cli/start-cli-net-vhost-dump-table.1 new file mode 100644 index 000000000..c6e89acc7 --- /dev/null +++ b/core/man/start-cli/start-cli-net-vhost-dump-table.1 @@ -0,0 +1,15 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-vhost-dump-table 1 "dump-table " +.SH NAME +start\-cli\-net\-vhost\-dump\-table +.SH SYNOPSIS +\fBstart\-cli net vhost dump\-table\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-vhost-list-passthrough.1 b/core/man/start-cli/start-cli-net-vhost-list-passthrough.1 new file mode 100644 index 000000000..a425795a2 --- /dev/null +++ b/core/man/start-cli/start-cli-net-vhost-list-passthrough.1 @@ -0,0 +1,15 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-vhost-list-passthrough 1 "list-passthrough " +.SH NAME +start\-cli\-net\-vhost\-list\-passthrough +.SH SYNOPSIS +\fBstart\-cli net vhost list\-passthrough\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-vhost-remove-passthrough.1 b/core/man/start-cli/start-cli-net-vhost-remove-passthrough.1 new file mode 100644 index 000000000..a444e2593 --- /dev/null +++ b/core/man/start-cli/start-cli-net-vhost-remove-passthrough.1 @@ -0,0 +1,18 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-vhost-remove-passthrough 1 "remove-passthrough " +.SH NAME +start\-cli\-net\-vhost\-remove\-passthrough +.SH SYNOPSIS +\fBstart\-cli net vhost remove\-passthrough\fR <\fB\-\-hostname\fR> <\fB\-\-listen\-port\fR> [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-\-hostname\fR \fI\fR + +.TP +\fB\-\-listen\-port\fR \fI\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-net-vhost.1 b/core/man/start-cli/start-cli-net-vhost.1 new file mode 100644 index 000000000..c977761fe --- /dev/null +++ b/core/man/start-cli/start-cli-net-vhost.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net-vhost 1 "vhost " +.SH NAME +start\-cli\-net\-vhost \- Manage SSL vhost proxy +.SH SYNOPSIS +\fBstart\-cli net vhost\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Manage SSL vhost proxy +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-net\-vhost\-add\-passthrough(1) +.TP +start\-cli\-net\-vhost\-dump\-table(1) +.TP +start\-cli\-net\-vhost\-list\-passthrough(1) +.TP +start\-cli\-net\-vhost\-remove\-passthrough(1) diff --git a/core/man/start-cli/start-cli-net.1 b/core/man/start-cli/start-cli-net.1 new file mode 100644 index 000000000..8fe2a8969 --- /dev/null +++ b/core/man/start-cli/start-cli-net.1 @@ -0,0 +1,32 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-net 1 "net " +.SH NAME +start\-cli\-net \- Network commands +.SH SYNOPSIS +\fBstart\-cli net\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Network commands +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-net\-acme(1) +Setup ACME certificate +.TP +start\-cli\-net\-dns(1) +Manage and query DNS +.TP +start\-cli\-net\-forward(1) +Manage port forwards +.TP +start\-cli\-net\-gateway(1) +View and edit gateway configurations +.TP +start\-cli\-net\-tunnel(1) +Manage tunnels +.TP +start\-cli\-net\-vhost(1) +Manage SSL vhost proxy diff --git a/core/man/start-cli/start-cli-notification-create.1 b/core/man/start-cli/start-cli-notification-create.1 new file mode 100644 index 000000000..d4bc03412 --- /dev/null +++ b/core/man/start-cli/start-cli-notification-create.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification-create 1 "create " +.SH NAME +start\-cli\-notification\-create \- Persist a new notification +.SH SYNOPSIS +\fBstart\-cli notification create\fR [\fB\-p\fR|\fB\-\-package\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fILEVEL\fR> <\fITITLE\fR> <\fIMESSAGE\fR> +.SH DESCRIPTION +Persist a new notification +.SH OPTIONS +.TP +\fB\-p\fR, \fB\-\-package\fR \fI\fR +Package identifier +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fILEVEL\fR> +Notification severity level +.TP +<\fITITLE\fR> +Notification title +.TP +<\fIMESSAGE\fR> +Notification message content diff --git a/core/man/start-cli/start-cli-notification-list.1 b/core/man/start-cli/start-cli-notification-list.1 new file mode 100644 index 000000000..03ced50b2 --- /dev/null +++ b/core/man/start-cli/start-cli-notification-list.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification-list 1 "list " +.SH NAME +start\-cli\-notification\-list \- List notifications +.SH SYNOPSIS +\fBstart\-cli notification list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIBEFORE\fR] [\fILIMIT\fR] +.SH DESCRIPTION +List notifications +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIBEFORE\fR] +Get notifications before this ID +.TP +[\fILIMIT\fR] +Maximum number of notifications to return diff --git a/core/man/start-cli/start-cli-notification-mark-seen-before.1 b/core/man/start-cli/start-cli-notification-mark-seen-before.1 new file mode 100644 index 000000000..c00a8d83a --- /dev/null +++ b/core/man/start-cli/start-cli-notification-mark-seen-before.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification-mark-seen-before 1 "mark-seen-before " +.SH NAME +start\-cli\-notification\-mark\-seen\-before \- Mark notifications as seen before a given ID +.SH SYNOPSIS +\fBstart\-cli notification mark\-seen\-before\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIBEFORE\fR> +.SH DESCRIPTION +Mark notifications as seen before a given ID +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIBEFORE\fR> +Get notifications before this ID diff --git a/core/man/start-cli/start-cli-notification-mark-seen.1 b/core/man/start-cli/start-cli-notification-mark-seen.1 new file mode 100644 index 000000000..d79a3fd86 --- /dev/null +++ b/core/man/start-cli/start-cli-notification-mark-seen.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification-mark-seen 1 "mark-seen " +.SH NAME +start\-cli\-notification\-mark\-seen \- Mark notifications as seen +.SH SYNOPSIS +\fBstart\-cli notification mark\-seen\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIIDS\fR] +.SH DESCRIPTION +Mark notifications as seen +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIIDS\fR] +Notification IDs diff --git a/core/man/start-cli/start-cli-notification-mark-unseen.1 b/core/man/start-cli/start-cli-notification-mark-unseen.1 new file mode 100644 index 000000000..d71d67dbb --- /dev/null +++ b/core/man/start-cli/start-cli-notification-mark-unseen.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification-mark-unseen 1 "mark-unseen " +.SH NAME +start\-cli\-notification\-mark\-unseen \- Mark notifications as unseen +.SH SYNOPSIS +\fBstart\-cli notification mark\-unseen\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIIDS\fR] +.SH DESCRIPTION +Mark notifications as unseen +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIIDS\fR] +Notification IDs diff --git a/core/man/start-cli/start-cli-notification-remove-before.1 b/core/man/start-cli/start-cli-notification-remove-before.1 new file mode 100644 index 000000000..8703cfba4 --- /dev/null +++ b/core/man/start-cli/start-cli-notification-remove-before.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification-remove-before 1 "remove-before " +.SH NAME +start\-cli\-notification\-remove\-before \- Remove notifications before a given ID +.SH SYNOPSIS +\fBstart\-cli notification remove\-before\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIBEFORE\fR> +.SH DESCRIPTION +Remove notifications before a given ID +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIBEFORE\fR> +Get notifications before this ID diff --git a/core/man/start-cli/start-cli-notification-remove.1 b/core/man/start-cli/start-cli-notification-remove.1 new file mode 100644 index 000000000..d198fd056 --- /dev/null +++ b/core/man/start-cli/start-cli-notification-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification-remove 1 "remove " +.SH NAME +start\-cli\-notification\-remove \- Remove notification for IDs +.SH SYNOPSIS +\fBstart\-cli notification remove\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIIDS\fR] +.SH DESCRIPTION +Remove notification for IDs +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIIDS\fR] +Notification IDs diff --git a/core/man/start-cli/start-cli-notification.1 b/core/man/start-cli/start-cli-notification.1 new file mode 100644 index 000000000..dfed2c598 --- /dev/null +++ b/core/man/start-cli/start-cli-notification.1 @@ -0,0 +1,35 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-notification 1 "notification " +.SH NAME +start\-cli\-notification \- Create, delete, or list notifications +.SH SYNOPSIS +\fBstart\-cli notification\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Create, delete, or list notifications +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-notification\-create(1) +Persist a new notification +.TP +start\-cli\-notification\-list(1) +List notifications +.TP +start\-cli\-notification\-mark\-seen(1) +Mark notifications as seen +.TP +start\-cli\-notification\-mark\-seen\-before(1) +Mark notifications as seen before a given ID +.TP +start\-cli\-notification\-mark\-unseen(1) +Mark notifications as unseen +.TP +start\-cli\-notification\-remove(1) +Remove notification for IDs +.TP +start\-cli\-notification\-remove\-before(1) +Remove notifications before a given ID diff --git a/core/man/start-cli/start-cli-package-action-clear-task.1 b/core/man/start-cli/start-cli-package-action-clear-task.1 new file mode 100644 index 000000000..8c2f46918 --- /dev/null +++ b/core/man/start-cli/start-cli-package-action-clear-task.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-action-clear-task 1 "clear-task " +.SH NAME +start\-cli\-package\-action\-clear\-task \- Clear a service task +.SH SYNOPSIS +\fBstart\-cli package action clear\-task\fR [\fB\-\-force\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIPACKAGE_ID\fR> <\fIREPLAY_ID\fR> +.SH DESCRIPTION +Clear a service task +.SH OPTIONS +.TP +\fB\-\-force\fR +Force clear the task even if running +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIPACKAGE_ID\fR> +Package identifier +.TP +<\fIREPLAY_ID\fR> +Replay identifier for task diff --git a/core/man/start-cli/start-cli-package-action-get-input.1 b/core/man/start-cli/start-cli-package-action-get-input.1 new file mode 100644 index 000000000..0b3aa9d1b --- /dev/null +++ b/core/man/start-cli/start-cli-package-action-get-input.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-action-get-input 1 "get-input " +.SH NAME +start\-cli\-package\-action\-get\-input \- Get action input specification +.SH SYNOPSIS +\fBstart\-cli package action get\-input\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIPACKAGE_ID\fR> <\fIACTION_ID\fR> +.SH DESCRIPTION +Get action input specification +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIPACKAGE_ID\fR> +Package identifier +.TP +<\fIACTION_ID\fR> +Action identifier diff --git a/core/man/start-cli/start-cli-package-action-run.1 b/core/man/start-cli/start-cli-package-action-run.1 new file mode 100644 index 000000000..81efe9aee --- /dev/null +++ b/core/man/start-cli/start-cli-package-action-run.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-action-run 1 "run " +.SH NAME +start\-cli\-package\-action\-run \- Run a service action +.SH SYNOPSIS +\fBstart\-cli package action run\fR [\fB\-\-event\-id\fR] [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIPACKAGE_ID\fR> <\fIACTION_ID\fR> +.SH DESCRIPTION +Run a service action +.SH OPTIONS +.TP +\fB\-\-event\-id\fR \fI\fR +Unique event identifier +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIPACKAGE_ID\fR> +Package identifier +.TP +<\fIACTION_ID\fR> +Action identifier diff --git a/core/man/start-cli/start-cli-package-action.1 b/core/man/start-cli/start-cli-package-action.1 new file mode 100644 index 000000000..375e2ef4b --- /dev/null +++ b/core/man/start-cli/start-cli-package-action.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-action 1 "action " +.SH NAME +start\-cli\-package\-action \- Commands to get action input or run an action +.SH SYNOPSIS +\fBstart\-cli package action\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to get action input or run an action +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-package\-action\-clear\-task(1) +Clear a service task +.TP +start\-cli\-package\-action\-get\-input(1) +Get action input specification +.TP +start\-cli\-package\-action\-run(1) +Run a service action diff --git a/core/man/start-cli/start-cli-package-attach.1 b/core/man/start-cli/start-cli-package-attach.1 new file mode 100644 index 000000000..b230689bf --- /dev/null +++ b/core/man/start-cli/start-cli-package-attach.1 @@ -0,0 +1,33 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-attach 1 "attach " +.SH NAME +start\-cli\-package\-attach +.SH SYNOPSIS +\fBstart\-cli package attach\fR [\fB\-\-force\-tty\fR] [\fB\-s\fR|\fB\-\-subcontainer\fR] [\fB\-n\fR|\fB\-\-name\fR] [\fB\-u\fR|\fB\-\-user\fR] [\fB\-i\fR|\fB\-\-image\-id\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> [\fICOMMAND\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-\-force\-tty\fR +Force TTY mode for I/O +.TP +\fB\-s\fR, \fB\-\-subcontainer\fR \fI\fR +Name of the subcontainer +.TP +\fB\-n\fR, \fB\-\-name\fR \fI\fR +Name of the container +.TP +\fB\-u\fR, \fB\-\-user\fR \fI\fR +User name to run as +.TP +\fB\-i\fR, \fB\-\-image\-id\fR \fI\fR +Docker image identifier +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier +.TP +[\fICOMMAND\fR] +Command to execute in the container diff --git a/core/man/start-cli/start-cli-package-backup-restore.1 b/core/man/start-cli/start-cli-package-backup-restore.1 new file mode 100644 index 000000000..144e74ab0 --- /dev/null +++ b/core/man/start-cli/start-cli-package-backup-restore.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-backup-restore 1 "restore " +.SH NAME +start\-cli\-package\-backup\-restore \- Restore packages from backup +.SH SYNOPSIS +\fBstart\-cli package backup restore\fR [\fB\-h\fR|\fB\-\-help\fR] <\fITARGET_ID\fR> <\fIPASSWORD\fR> [\fIIDS\fR] +.SH DESCRIPTION +Restore packages from backup +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fITARGET_ID\fR> +Backup target identifier +.TP +<\fIPASSWORD\fR> +Password for backup encryption +.TP +[\fIIDS\fR] +Package identifiers diff --git a/core/man/start-cli/start-cli-package-backup.1 b/core/man/start-cli/start-cli-package-backup.1 new file mode 100644 index 000000000..02fd83765 --- /dev/null +++ b/core/man/start-cli/start-cli-package-backup.1 @@ -0,0 +1,17 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-backup 1 "backup " +.SH NAME +start\-cli\-package\-backup \- Commands for restoring package(s) from backup +.SH SYNOPSIS +\fBstart\-cli package backup\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands for restoring package(s) from backup +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-package\-backup\-restore(1) +Restore packages from backup diff --git a/core/man/start-cli/start-cli-package-cancel-install.1 b/core/man/start-cli/start-cli-package-cancel-install.1 new file mode 100644 index 000000000..33dc1c34e --- /dev/null +++ b/core/man/start-cli/start-cli-package-cancel-install.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-cancel-install 1 "cancel-install " +.SH NAME +start\-cli\-package\-cancel\-install \- Cancel an install of a package +.SH SYNOPSIS +\fBstart\-cli package cancel\-install\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Cancel an install of a package +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package-host-address-domain-private-add.1 b/core/man/start-cli/start-cli-package-host-address-domain-private-add.1 new file mode 100644 index 000000000..f40a9b74c --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-domain-private-add.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-domain-private-add 1 "add " +.SH NAME +start\-cli\-package\-host\-address\-domain\-private\-add \- Add a private domain to this host +.SH SYNOPSIS +\fBstart\-cli package host address domain private add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> <\fIGATEWAY\fR> +.SH DESCRIPTION +Add a private domain to this host +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name +.TP +<\fIGATEWAY\fR> + diff --git a/core/man/start-cli/start-cli-package-host-address-domain-private-remove.1 b/core/man/start-cli/start-cli-package-host-address-domain-private-remove.1 new file mode 100644 index 000000000..090938017 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-domain-private-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-domain-private-remove 1 "remove " +.SH NAME +start\-cli\-package\-host\-address\-domain\-private\-remove \- Remove private domain from host +.SH SYNOPSIS +\fBstart\-cli package host address domain private remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> +.SH DESCRIPTION +Remove private domain from host +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name diff --git a/core/man/start-cli/start-cli-package-host-address-domain-private.1 b/core/man/start-cli/start-cli-package-host-address-domain-private.1 new file mode 100644 index 000000000..823896bdb --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-domain-private.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-domain-private 1 "private " +.SH NAME +start\-cli\-package\-host\-address\-domain\-private +.SH SYNOPSIS +\fBstart\-cli package host address domain private\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-package\-host\-address\-domain\-private\-add(1) +Add a private domain to this host +.TP +start\-cli\-package\-host\-address\-domain\-private\-remove(1) +Remove private domain from host diff --git a/core/man/start-cli/start-cli-package-host-address-domain-public-add.1 b/core/man/start-cli/start-cli-package-host-address-domain-public-add.1 new file mode 100644 index 000000000..b30b1e6da --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-domain-public-add.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-domain-public-add 1 "add " +.SH NAME +start\-cli\-package\-host\-address\-domain\-public\-add \- Add a public domain to this host +.SH SYNOPSIS +\fBstart\-cli package host address domain public add\fR [\fB\-\-acme\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> <\fIGATEWAY\fR> <\fIINTERNAL_PORT\fR> +.SH DESCRIPTION +Add a public domain to this host +.SH OPTIONS +.TP +\fB\-\-acme\fR \fI\fR +ACME provider identifier or url +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name +.TP +<\fIGATEWAY\fR> +Gateway identifier +.TP +<\fIINTERNAL_PORT\fR> +Internal port number diff --git a/core/man/start-cli/start-cli-package-host-address-domain-public-remove.1 b/core/man/start-cli/start-cli-package-host-address-domain-public-remove.1 new file mode 100644 index 000000000..3c99dd2dc --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-domain-public-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-domain-public-remove 1 "remove " +.SH NAME +start\-cli\-package\-host\-address\-domain\-public\-remove \- Remove public domain from host +.SH SYNOPSIS +\fBstart\-cli package host address domain public remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> +.SH DESCRIPTION +Remove public domain from host +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name diff --git a/core/man/start-cli/start-cli-package-host-address-domain-public.1 b/core/man/start-cli/start-cli-package-host-address-domain-public.1 new file mode 100644 index 000000000..096c50bb8 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-domain-public.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-domain-public 1 "public " +.SH NAME +start\-cli\-package\-host\-address\-domain\-public +.SH SYNOPSIS +\fBstart\-cli package host address domain public\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-package\-host\-address\-domain\-public\-add(1) +Add a public domain to this host +.TP +start\-cli\-package\-host\-address\-domain\-public\-remove(1) +Remove public domain from host diff --git a/core/man/start-cli/start-cli-package-host-address-domain.1 b/core/man/start-cli/start-cli-package-host-address-domain.1 new file mode 100644 index 000000000..e80a1a407 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-domain.1 @@ -0,0 +1,17 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-domain 1 "domain " +.SH NAME +start\-cli\-package\-host\-address\-domain +.SH SYNOPSIS +\fBstart\-cli package host address domain\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-package\-host\-address\-domain\-private(1) +.TP +start\-cli\-package\-host\-address\-domain\-public(1) diff --git a/core/man/start-cli/start-cli-package-host-address-list.1 b/core/man/start-cli/start-cli-package-host-address-list.1 new file mode 100644 index 000000000..c28cd6a47 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address-list 1 "list " +.SH NAME +start\-cli\-package\-host\-address\-list \- List addresses for a host +.SH SYNOPSIS +\fBstart\-cli package host address list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List addresses for a host +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-package-host-address.1 b/core/man/start-cli/start-cli-package-host-address.1 new file mode 100644 index 000000000..3c9709fe1 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-address.1 @@ -0,0 +1,21 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-address 1 "address " +.SH NAME +start\-cli\-package\-host\-address +.SH SYNOPSIS +\fBstart\-cli package host address\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIHOST\fR> <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIHOST\fR> +Host identifier +.SH SUBCOMMANDS +.TP +start\-cli\-package\-host\-address\-domain(1) +.TP +start\-cli\-package\-host\-address\-list(1) +List addresses for a host diff --git a/core/man/start-cli/start-cli-package-host-binding-list.1 b/core/man/start-cli/start-cli-package-host-binding-list.1 new file mode 100644 index 000000000..e26168089 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-binding-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-binding-list 1 "list " +.SH NAME +start\-cli\-package\-host\-binding\-list \- List bindings for a host +.SH SYNOPSIS +\fBstart\-cli package host binding list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List bindings for a host +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-package-host-binding-set-address-enabled.1 b/core/man/start-cli/start-cli-package-host-binding-set-address-enabled.1 new file mode 100644 index 000000000..b0cd6bb41 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-binding-set-address-enabled.1 @@ -0,0 +1,32 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-binding-set-address-enabled 1 "set-address-enabled " +.SH NAME +start\-cli\-package\-host\-binding\-set\-address\-enabled \- about.set\-address\-enabled\-for\-binding +.SH SYNOPSIS +\fBstart\-cli package host binding set\-address\-enabled\fR <\fB\-\-address\fR> [\fB\-\-enabled\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIINTERNAL_PORT\fR> +.SH DESCRIPTION +about.set\-address\-enabled\-for\-binding +.SH OPTIONS +.TP +\fB\-\-address\fR \fI
\fR +help.arg.address +.TP +\fB\-\-enabled\fR \fI\fR +Enable or disable this binding +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +true +.IP \(bu 2 +false +.RE +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIINTERNAL_PORT\fR> +Internal port number diff --git a/core/man/start-cli/start-cli-package-host-binding.1 b/core/man/start-cli/start-cli-package-host-binding.1 new file mode 100644 index 000000000..ebdf88882 --- /dev/null +++ b/core/man/start-cli/start-cli-package-host-binding.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host-binding 1 "binding " +.SH NAME +start\-cli\-package\-host\-binding +.SH SYNOPSIS +\fBstart\-cli package host binding\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIHOST\fR> <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIHOST\fR> +Host identifier +.SH SUBCOMMANDS +.TP +start\-cli\-package\-host\-binding\-list(1) +List bindings for a host +.TP +start\-cli\-package\-host\-binding\-set\-address\-enabled(1) +about.set\-address\-enabled\-for\-binding diff --git a/core/man/start-cli/start-cli-package-host.1 b/core/man/start-cli/start-cli-package-host.1 new file mode 100644 index 000000000..eb980510b --- /dev/null +++ b/core/man/start-cli/start-cli-package-host.1 @@ -0,0 +1,21 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-host 1 "host " +.SH NAME +start\-cli\-package\-host \- Manage network hosts for a package +.SH SYNOPSIS +\fBstart\-cli package host\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIPACKAGE\fR> <\fIsubcommands\fR> +.SH DESCRIPTION +Manage network hosts for a package +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIPACKAGE\fR> +Package identifier +.SH SUBCOMMANDS +.TP +start\-cli\-package\-host\-address(1) +.TP +start\-cli\-package\-host\-binding(1) diff --git a/core/man/start-cli/start-cli-package-install.1 b/core/man/start-cli/start-cli-package-install.1 new file mode 100644 index 000000000..023cd77f7 --- /dev/null +++ b/core/man/start-cli/start-cli-package-install.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-install 1 "install " +.SH NAME +start\-cli\-package\-install \- Install a package +.SH SYNOPSIS +\fBstart\-cli package install\fR [\fB\-s\fR|\fB\-\-sideload\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIID\fR] [\fIVERSION\fR] +.SH DESCRIPTION +Install a package +.SH OPTIONS +.TP +\fB\-s\fR, \fB\-\-sideload\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIID\fR] +Package identifier +.TP +[\fIVERSION\fR] +Version range constraint diff --git a/core/man/start-cli/start-cli-package-installed-version.1 b/core/man/start-cli/start-cli-package-installed-version.1 new file mode 100644 index 000000000..43cfadcbd --- /dev/null +++ b/core/man/start-cli/start-cli-package-installed-version.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-installed-version 1 "installed-version " +.SH NAME +start\-cli\-package\-installed\-version \- Display the installed version of a package +.SH SYNOPSIS +\fBstart\-cli package installed\-version\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Display the installed version of a package +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package-list.1 b/core/man/start-cli/start-cli-package-list.1 new file mode 100644 index 000000000..279047672 --- /dev/null +++ b/core/man/start-cli/start-cli-package-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-list 1 "list " +.SH NAME +start\-cli\-package\-list \- List installed packages +.SH SYNOPSIS +\fBstart\-cli package list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List installed packages +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-package-logs.1 b/core/man/start-cli/start-cli-package-logs.1 new file mode 100644 index 000000000..dd6fb5571 --- /dev/null +++ b/core/man/start-cli/start-cli-package-logs.1 @@ -0,0 +1,31 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-logs 1 "logs " +.SH NAME +start\-cli\-package\-logs \- Display logs for a package +.SH SYNOPSIS +\fBstart\-cli package logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Display logs for a package +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package-rebuild.1 b/core/man/start-cli/start-cli-package-rebuild.1 new file mode 100644 index 000000000..c7b26ce9d --- /dev/null +++ b/core/man/start-cli/start-cli-package-rebuild.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-rebuild 1 "rebuild " +.SH NAME +start\-cli\-package\-rebuild \- Rebuild service container +.SH SYNOPSIS +\fBstart\-cli package rebuild\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Rebuild service container +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package-restart.1 b/core/man/start-cli/start-cli-package-restart.1 new file mode 100644 index 000000000..7582f726f --- /dev/null +++ b/core/man/start-cli/start-cli-package-restart.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-restart 1 "restart " +.SH NAME +start\-cli\-package\-restart \- Restart a service +.SH SYNOPSIS +\fBstart\-cli package restart\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Restart a service +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package-set-outbound-gateway.1 b/core/man/start-cli/start-cli-package-set-outbound-gateway.1 new file mode 100644 index 000000000..57c4b7b31 --- /dev/null +++ b/core/man/start-cli/start-cli-package-set-outbound-gateway.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-set-outbound-gateway 1 "set-outbound-gateway " +.SH NAME +start\-cli\-package\-set\-outbound\-gateway \- about.set\-outbound\-gateway\-package +.SH SYNOPSIS +\fBstart\-cli package set\-outbound\-gateway\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIPACKAGE\fR> [\fIGATEWAY\fR] +.SH DESCRIPTION +about.set\-outbound\-gateway\-package +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIPACKAGE\fR> +Package identifier +.TP +[\fIGATEWAY\fR] +Gateway identifier diff --git a/core/man/start-cli/start-cli-package-start.1 b/core/man/start-cli/start-cli-package-start.1 new file mode 100644 index 000000000..0fbddfdb5 --- /dev/null +++ b/core/man/start-cli/start-cli-package-start.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-start 1 "start " +.SH NAME +start\-cli\-package\-start \- Start a service +.SH SYNOPSIS +\fBstart\-cli package start\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Start a service +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package-stats.1 b/core/man/start-cli/start-cli-package-stats.1 new file mode 100644 index 000000000..9e55fe888 --- /dev/null +++ b/core/man/start-cli/start-cli-package-stats.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-stats 1 "stats " +.SH NAME +start\-cli\-package\-stats \- List LXC container information +.SH SYNOPSIS +\fBstart\-cli package stats\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List LXC container information +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-package-stop.1 b/core/man/start-cli/start-cli-package-stop.1 new file mode 100644 index 000000000..087541683 --- /dev/null +++ b/core/man/start-cli/start-cli-package-stop.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-stop 1 "stop " +.SH NAME +start\-cli\-package\-stop \- Stop a service +.SH SYNOPSIS +\fBstart\-cli package stop\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Stop a service +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package-uninstall.1 b/core/man/start-cli/start-cli-package-uninstall.1 new file mode 100644 index 000000000..2a1e69c13 --- /dev/null +++ b/core/man/start-cli/start-cli-package-uninstall.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package-uninstall 1 "uninstall " +.SH NAME +start\-cli\-package\-uninstall \- Remove a package +.SH SYNOPSIS +\fBstart\-cli package uninstall\fR [\fB\-\-soft\fR] [\fB\-\-force\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Remove a package +.SH OPTIONS +.TP +\fB\-\-soft\fR +Uninstall without deleting service data +.TP +\fB\-\-force\fR +Ignore errors in service uninit script +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-package.1 b/core/man/start-cli/start-cli-package.1 new file mode 100644 index 000000000..894fa0b37 --- /dev/null +++ b/core/man/start-cli/start-cli-package.1 @@ -0,0 +1,61 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-package 1 "package " +.SH NAME +start\-cli\-package \- Commands related to packages +.SH SYNOPSIS +\fBstart\-cli package\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to packages +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-package\-action(1) +Commands to get action input or run an action +.TP +start\-cli\-package\-attach(1) +.TP +start\-cli\-package\-backup(1) +Commands for restoring package(s) from backup +.TP +start\-cli\-package\-cancel\-install(1) +Cancel an install of a package +.TP +start\-cli\-package\-host(1) +Manage network hosts for a package +.TP +start\-cli\-package\-install(1) +Install a package +.TP +start\-cli\-package\-installed\-version(1) +Display the installed version of a package +.TP +start\-cli\-package\-list(1) +List installed packages +.TP +start\-cli\-package\-logs(1) +Display logs for a package +.TP +start\-cli\-package\-rebuild(1) +Rebuild service container +.TP +start\-cli\-package\-restart(1) +Restart a service +.TP +start\-cli\-package\-set\-outbound\-gateway(1) +about.set\-outbound\-gateway\-package +.TP +start\-cli\-package\-start(1) +Start a service +.TP +start\-cli\-package\-stats(1) +List LXC container information +.TP +start\-cli\-package\-stop(1) +Stop a service +.TP +start\-cli\-package\-uninstall(1) +Remove a package diff --git a/core/man/start-cli/start-cli-pubkey.1 b/core/man/start-cli/start-cli-pubkey.1 new file mode 100644 index 000000000..5de15da8e --- /dev/null +++ b/core/man/start-cli/start-cli-pubkey.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-pubkey 1 "pubkey " +.SH NAME +start\-cli\-pubkey \- Get the developer public key +.SH SYNOPSIS +\fBstart\-cli pubkey\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Get the developer public key +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-admin-add.1 b/core/man/start-cli/start-cli-registry-admin-add.1 new file mode 100644 index 000000000..b96f8e407 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin-add.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin-add 1 "add " +.SH NAME +start\-cli\-registry\-admin\-add \- Add admin signer +.SH SYNOPSIS +\fBstart\-cli registry admin add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISIGNER\fR> [\fIDATABASE\fR] +.SH DESCRIPTION +Add admin signer +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISIGNER\fR> +Signer identifier +.TP +[\fIDATABASE\fR] +Path to the database file diff --git a/core/man/start-cli/start-cli-registry-admin-list.1 b/core/man/start-cli/start-cli-registry-admin-list.1 new file mode 100644 index 000000000..5a1433140 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin-list 1 "list " +.SH NAME +start\-cli\-registry\-admin\-list \- List admin signers +.SH SYNOPSIS +\fBstart\-cli registry admin list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List admin signers +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-admin-remove.1 b/core/man/start-cli/start-cli-registry-admin-remove.1 new file mode 100644 index 000000000..7028f9b36 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin-remove 1 "remove " +.SH NAME +start\-cli\-registry\-admin\-remove \- Remove admin signer +.SH SYNOPSIS +\fBstart\-cli registry admin remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISIGNER\fR> +.SH DESCRIPTION +Remove admin signer +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISIGNER\fR> +Signer identifier diff --git a/core/man/start-cli/start-cli-registry-admin-signer-add.1 b/core/man/start-cli/start-cli-registry-admin-signer-add.1 new file mode 100644 index 000000000..201c97103 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin-signer-add.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin-signer-add 1 "add " +.SH NAME +start\-cli\-registry\-admin\-signer\-add \- Add signer +.SH SYNOPSIS +\fBstart\-cli registry admin signer add\fR <\fB\-n\fR|\fB\-\-name\fR> [\fB\-c\fR|\fB\-\-contact\fR] [\fB\-\-key\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIDATABASE\fR] +.SH DESCRIPTION +Add signer +.SH OPTIONS +.TP +\fB\-n\fR, \fB\-\-name\fR \fI\fR +Name of the signer +.TP +\fB\-c\fR, \fB\-\-contact\fR \fI\fR +Contact information for signer +.TP +\fB\-\-key\fR \fI\fR +Public key for signer +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIDATABASE\fR] +Path to the database file diff --git a/core/man/start-cli/start-cli-registry-admin-signer-edit.1 b/core/man/start-cli/start-cli-registry-admin-signer-edit.1 new file mode 100644 index 000000000..2d0a3f6e9 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin-signer-edit.1 @@ -0,0 +1,31 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin-signer-edit 1 "edit " +.SH NAME +start\-cli\-registry\-admin\-signer\-edit \- Edit signer information +.SH SYNOPSIS +\fBstart\-cli registry admin signer edit\fR [\fB\-n\fR|\fB\-\-set\-name\fR] [\fB\-c\fR|\fB\-\-add\-contact\fR] [\fB\-k\fR|\fB\-\-add\-key\fR] [\fB\-C\fR|\fB\-\-remove\-contact\fR] [\fB\-K\fR|\fB\-\-remove\-key\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Edit signer information +.SH OPTIONS +.TP +\fB\-n\fR, \fB\-\-set\-name\fR \fI\fR +Set the signer name +.TP +\fB\-c\fR, \fB\-\-add\-contact\fR \fI\fR +Add contact information to signer +.TP +\fB\-k\fR, \fB\-\-add\-key\fR \fI\fR +Add a public key to signer +.TP +\fB\-C\fR, \fB\-\-remove\-contact\fR \fI\fR +Remove contact from signer +.TP +\fB\-K\fR, \fB\-\-remove\-key\fR \fI\fR +Remove public key from signer +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Signer identifier diff --git a/core/man/start-cli/start-cli-registry-admin-signer-list.1 b/core/man/start-cli/start-cli-registry-admin-signer-list.1 new file mode 100644 index 000000000..b87068031 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin-signer-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin-signer-list 1 "list " +.SH NAME +start\-cli\-registry\-admin\-signer\-list \- List signers +.SH SYNOPSIS +\fBstart\-cli registry admin signer list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List signers +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-admin-signer.1 b/core/man/start-cli/start-cli-registry-admin-signer.1 new file mode 100644 index 000000000..ad360c9d4 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin-signer.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin-signer 1 "signer " +.SH NAME +start\-cli\-registry\-admin\-signer \- Commands to add or list signers +.SH SYNOPSIS +\fBstart\-cli registry admin signer\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to add or list signers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-admin\-signer\-add(1) +Add signer +.TP +start\-cli\-registry\-admin\-signer\-edit(1) +Edit signer information +.TP +start\-cli\-registry\-admin\-signer\-list(1) +List signers diff --git a/core/man/start-cli/start-cli-registry-admin.1 b/core/man/start-cli/start-cli-registry-admin.1 new file mode 100644 index 000000000..472313bc3 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-admin.1 @@ -0,0 +1,26 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-admin 1 "admin " +.SH NAME +start\-cli\-registry\-admin \- Commands to add or list admins or signers +.SH SYNOPSIS +\fBstart\-cli registry admin\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to add or list admins or signers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-admin\-add(1) +Add admin signer +.TP +start\-cli\-registry\-admin\-list(1) +List admin signers +.TP +start\-cli\-registry\-admin\-remove(1) +Remove admin signer +.TP +start\-cli\-registry\-admin\-signer(1) +Commands to add or list signers diff --git a/core/man/start-cli/start-cli-registry-db-apply.1 b/core/man/start-cli/start-cli-registry-db-apply.1 new file mode 100644 index 000000000..9d2536595 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-db-apply.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-db-apply 1 "apply " +.SH NAME +start\-cli\-registry\-db\-apply \- Update a database record +.SH SYNOPSIS +\fBstart\-cli registry db apply\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIEXPR\fR> [\fIPATH\fR] +.SH DESCRIPTION +Update a database record +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIEXPR\fR> +Database patch expression to apply +.TP +[\fIPATH\fR] +Path to the database file diff --git a/core/man/start-cli/start-cli-registry-db-dump.1 b/core/man/start-cli/start-cli-registry-db-dump.1 new file mode 100644 index 000000000..8c1e11666 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-db-dump.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-db-dump 1 "dump " +.SH NAME +start\-cli\-registry\-db\-dump \- Filter and query the database +.SH SYNOPSIS +\fBstart\-cli registry db dump\fR [\fB\-p\fR|\fB\-\-pointer\fR] [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIPATH\fR] +.SH DESCRIPTION +Filter and query the database +.SH OPTIONS +.TP +\fB\-p\fR, \fB\-\-pointer\fR \fI\fR +JSON pointer to object in database to dump +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIPATH\fR] +Path to the database file diff --git a/core/man/start-cli/start-cli-registry-db.1 b/core/man/start-cli/start-cli-registry-db.1 new file mode 100644 index 000000000..c0d4e0a2a --- /dev/null +++ b/core/man/start-cli/start-cli-registry-db.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-db 1 "db " +.SH NAME +start\-cli\-registry\-db \- Commands to interact with the db i.e. dump and apply +.SH SYNOPSIS +\fBstart\-cli registry db\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to interact with the db i.e. dump and apply +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-db\-apply(1) +Update a database record +.TP +start\-cli\-registry\-db\-dump(1) +Filter and query the database diff --git a/core/man/start-cli/start-cli-registry-index.1 b/core/man/start-cli/start-cli-registry-index.1 new file mode 100644 index 000000000..497750d4b --- /dev/null +++ b/core/man/start-cli/start-cli-registry-index.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-index 1 "index " +.SH NAME +start\-cli\-registry\-index \- List registry info and packages +.SH SYNOPSIS +\fBstart\-cli registry index\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List registry info and packages +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-info-set-icon.1 b/core/man/start-cli/start-cli-registry-info-set-icon.1 new file mode 100644 index 000000000..2cb688f5f --- /dev/null +++ b/core/man/start-cli/start-cli-registry-info-set-icon.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-info-set-icon 1 "set-icon " +.SH NAME +start\-cli\-registry\-info\-set\-icon \- Set the registry icon +.SH SYNOPSIS +\fBstart\-cli registry info set\-icon\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIICON\fR> +.SH DESCRIPTION +Set the registry icon +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIICON\fR> +Path to service icon file diff --git a/core/man/start-cli/start-cli-registry-info-set-name.1 b/core/man/start-cli/start-cli-registry-info-set-name.1 new file mode 100644 index 000000000..cc01d360f --- /dev/null +++ b/core/man/start-cli/start-cli-registry-info-set-name.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-info-set-name 1 "set-name " +.SH NAME +start\-cli\-registry\-info\-set\-name \- Set the registry name +.SH SYNOPSIS +\fBstart\-cli registry info set\-name\fR [\fB\-h\fR|\fB\-\-help\fR] <\fINAME\fR> +.SH DESCRIPTION +Set the registry name +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fINAME\fR> +Name of the registry diff --git a/core/man/start-cli/start-cli-registry-info.1 b/core/man/start-cli/start-cli-registry-info.1 new file mode 100644 index 000000000..8556dbd3b --- /dev/null +++ b/core/man/start-cli/start-cli-registry-info.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-info 1 "info " +.SH NAME +start\-cli\-registry\-info \- Display registry info +.SH SYNOPSIS +\fBstart\-cli registry info\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIsubcommands\fR] +.SH DESCRIPTION +Display registry info +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-info\-set\-icon(1) +Set the registry icon +.TP +start\-cli\-registry\-info\-set\-name(1) +Set the registry name diff --git a/core/man/start-cli/start-cli-registry-os-asset-add.1 b/core/man/start-cli/start-cli-registry-os-asset-add.1 new file mode 100644 index 000000000..34d484abc --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset-add.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset-add 1 "add " +.SH NAME +start\-cli\-registry\-os\-asset\-add \- Add asset to registry +.SH SYNOPSIS +\fBstart\-cli registry os asset add\fR <\fB\-p\fR|\fB\-\-platform\fR> <\fB\-v\fR|\fB\-\-version\fR> [\fB\-h\fR|\fB\-\-help\fR] <\fIFILE\fR> <\fIURL\fR> +.SH DESCRIPTION +Add asset to registry +.SH OPTIONS +.TP +\fB\-p\fR, \fB\-\-platform\fR \fI\fR +Target platform identifier +.TP +\fB\-v\fR, \fB\-\-version\fR \fI\fR +StartOS version number +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFILE\fR> +Path to the asset file +.TP +<\fIURL\fR> +URL of the asset diff --git a/core/man/start-cli/start-cli-registry-os-asset-get-img.1 b/core/man/start-cli/start-cli-registry-os-asset-get-img.1 new file mode 100644 index 000000000..d69e2f0e0 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset-get-img.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset-get-img 1 "img " +.SH NAME +start\-cli\-registry\-os\-asset\-get\-img \- Download IMG file +.SH SYNOPSIS +\fBstart\-cli registry os asset get img\fR [\fB\-d\fR|\fB\-\-download\fR] [\fB\-r\fR|\fB\-\-reverify\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> <\fIPLATFORM\fR> +.SH DESCRIPTION +Download IMG file +.SH OPTIONS +.TP +\fB\-d\fR, \fB\-\-download\fR \fI\fR +Directory path to download to +.TP +\fB\-r\fR, \fB\-\-reverify\fR +Verify hash after download completes +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> +StartOS version number +.TP +<\fIPLATFORM\fR> +Target platform identifier diff --git a/core/man/start-cli/start-cli-registry-os-asset-get-iso.1 b/core/man/start-cli/start-cli-registry-os-asset-get-iso.1 new file mode 100644 index 000000000..f71128e47 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset-get-iso.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset-get-iso 1 "iso " +.SH NAME +start\-cli\-registry\-os\-asset\-get\-iso \- Download ISO file +.SH SYNOPSIS +\fBstart\-cli registry os asset get iso\fR [\fB\-d\fR|\fB\-\-download\fR] [\fB\-r\fR|\fB\-\-reverify\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> <\fIPLATFORM\fR> +.SH DESCRIPTION +Download ISO file +.SH OPTIONS +.TP +\fB\-d\fR, \fB\-\-download\fR \fI\fR +Directory path to download to +.TP +\fB\-r\fR, \fB\-\-reverify\fR +Verify hash after download completes +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> +StartOS version number +.TP +<\fIPLATFORM\fR> +Target platform identifier diff --git a/core/man/start-cli/start-cli-registry-os-asset-get-squashfs.1 b/core/man/start-cli/start-cli-registry-os-asset-get-squashfs.1 new file mode 100644 index 000000000..80a4aefdd --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset-get-squashfs.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset-get-squashfs 1 "squashfs " +.SH NAME +start\-cli\-registry\-os\-asset\-get\-squashfs \- Download squashfs file +.SH SYNOPSIS +\fBstart\-cli registry os asset get squashfs\fR [\fB\-d\fR|\fB\-\-download\fR] [\fB\-r\fR|\fB\-\-reverify\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> <\fIPLATFORM\fR> +.SH DESCRIPTION +Download squashfs file +.SH OPTIONS +.TP +\fB\-d\fR, \fB\-\-download\fR \fI\fR +Directory path to download to +.TP +\fB\-r\fR, \fB\-\-reverify\fR +Verify hash after download completes +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> +StartOS version number +.TP +<\fIPLATFORM\fR> +Target platform identifier diff --git a/core/man/start-cli/start-cli-registry-os-asset-get.1 b/core/man/start-cli/start-cli-registry-os-asset-get.1 new file mode 100644 index 000000000..4e7a4c611 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset-get.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset-get 1 "get " +.SH NAME +start\-cli\-registry\-os\-asset\-get \- Commands to download image, iso, or squashfs files +.SH SYNOPSIS +\fBstart\-cli registry os asset get\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to download image, iso, or squashfs files +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-os\-asset\-get\-img(1) +Download IMG file +.TP +start\-cli\-registry\-os\-asset\-get\-iso(1) +Download ISO file +.TP +start\-cli\-registry\-os\-asset\-get\-squashfs(1) +Download squashfs file diff --git a/core/man/start-cli/start-cli-registry-os-asset-remove.1 b/core/man/start-cli/start-cli-registry-os-asset-remove.1 new file mode 100644 index 000000000..f1bf2aacb --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset-remove.1 @@ -0,0 +1,12 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset-remove 1 "remove " +.SH NAME +start\-cli\-registry\-os\-asset\-remove +.SH SYNOPSIS +\fBstart\-cli registry os asset remove\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-os-asset-sign.1 b/core/man/start-cli/start-cli-registry-os-asset-sign.1 new file mode 100644 index 000000000..1316e1f05 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset-sign.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset-sign 1 "sign " +.SH NAME +start\-cli\-registry\-os\-asset\-sign \- Sign file and add to registry +.SH SYNOPSIS +\fBstart\-cli registry os asset sign\fR <\fB\-p\fR|\fB\-\-platform\fR> <\fB\-v\fR|\fB\-\-version\fR> [\fB\-h\fR|\fB\-\-help\fR] <\fIFILE\fR> +.SH DESCRIPTION +Sign file and add to registry +.SH OPTIONS +.TP +\fB\-p\fR, \fB\-\-platform\fR \fI\fR +Target platform identifier +.TP +\fB\-v\fR, \fB\-\-version\fR \fI\fR +StartOS version number +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFILE\fR> +Path to the asset file diff --git a/core/man/start-cli/start-cli-registry-os-asset.1 b/core/man/start-cli/start-cli-registry-os-asset.1 new file mode 100644 index 000000000..95f6ae704 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-asset.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-asset 1 "asset " +.SH NAME +start\-cli\-registry\-os\-asset \- Commands to add, sign, or get registry assets +.SH SYNOPSIS +\fBstart\-cli registry os asset\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to add, sign, or get registry assets +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-os\-asset\-add(1) +Add asset to registry +.TP +start\-cli\-registry\-os\-asset\-get(1) +Commands to download image, iso, or squashfs files +.TP +start\-cli\-registry\-os\-asset\-remove(1) +.TP +start\-cli\-registry\-os\-asset\-sign(1) +Sign file and add to registry diff --git a/core/man/start-cli/start-cli-registry-os-index.1 b/core/man/start-cli/start-cli-registry-os-index.1 new file mode 100644 index 000000000..8ec4f1859 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-index.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-index 1 "index " +.SH NAME +start\-cli\-registry\-os\-index \- List OS versions index +.SH SYNOPSIS +\fBstart\-cli registry os index\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List OS versions index +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-os-version-add.1 b/core/man/start-cli/start-cli-registry-os-version-add.1 new file mode 100644 index 000000000..d2a3f7974 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version-add.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version-add 1 "add " +.SH NAME +start\-cli\-registry\-os\-version\-add \- Add OS version +.SH SYNOPSIS +\fBstart\-cli registry os version add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> <\fIHEADLINE\fR> <\fIRELEASE_NOTES\fR> <\fISOURCE_VERSION\fR> +.SH DESCRIPTION +Add OS version +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> +StartOS version number +.TP +<\fIHEADLINE\fR> +Short headline for the version +.TP +<\fIRELEASE_NOTES\fR> +Release notes for this version +.TP +<\fISOURCE_VERSION\fR> +Source version range for migration diff --git a/core/man/start-cli/start-cli-registry-os-version-get.1 b/core/man/start-cli/start-cli-registry-os-version-get.1 new file mode 100644 index 000000000..4a411b055 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version-get.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version-get 1 "get " +.SH NAME +start\-cli\-registry\-os\-version\-get \- Get OS versions info +.SH SYNOPSIS +\fBstart\-cli registry os version get\fR [\fB\-\-src\fR] [\fB\-\-target\-version\fR] [\fB\-\-id\fR] [\fB\-\-platform\fR] [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Get OS versions info +.SH OPTIONS +.TP +\fB\-\-src\fR \fI\fR +Source version to upgrade from +.TP +\fB\-\-target\-version\fR \fI\fR +Target version range constraint +.TP +\fB\-\-id\fR \fI\fR +Unique server identifier +.TP +\fB\-\-platform\fR \fI\fR +Target platform identifier +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-os-version-remove.1 b/core/man/start-cli/start-cli-registry-os-version-remove.1 new file mode 100644 index 000000000..bec6b7af1 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version-remove 1 "remove " +.SH NAME +start\-cli\-registry\-os\-version\-remove \- Remove OS version +.SH SYNOPSIS +\fBstart\-cli registry os version remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> +.SH DESCRIPTION +Remove OS version +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> +StartOS version number diff --git a/core/man/start-cli/start-cli-registry-os-version-signer-add.1 b/core/man/start-cli/start-cli-registry-os-version-signer-add.1 new file mode 100644 index 000000000..38baa3e36 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version-signer-add.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version-signer-add 1 "add " +.SH NAME +start\-cli\-registry\-os\-version\-signer\-add \- Add version signer +.SH SYNOPSIS +\fBstart\-cli registry os version signer add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> <\fISIGNER\fR> +.SH DESCRIPTION +Add version signer +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> + +.TP +<\fISIGNER\fR> + diff --git a/core/man/start-cli/start-cli-registry-os-version-signer-list.1 b/core/man/start-cli/start-cli-registry-os-version-signer-list.1 new file mode 100644 index 000000000..3f18d1d69 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version-signer-list.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version-signer-list 1 "list " +.SH NAME +start\-cli\-registry\-os\-version\-signer\-list \- List version signers +.SH SYNOPSIS +\fBstart\-cli registry os version signer list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> +.SH DESCRIPTION +List version signers +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> + diff --git a/core/man/start-cli/start-cli-registry-os-version-signer-remove.1 b/core/man/start-cli/start-cli-registry-os-version-signer-remove.1 new file mode 100644 index 000000000..2a650ff39 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version-signer-remove.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version-signer-remove 1 "remove " +.SH NAME +start\-cli\-registry\-os\-version\-signer\-remove \- Remove version signer +.SH SYNOPSIS +\fBstart\-cli registry os version signer remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIVERSION\fR> <\fISIGNER\fR> +.SH DESCRIPTION +Remove version signer +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIVERSION\fR> + +.TP +<\fISIGNER\fR> + diff --git a/core/man/start-cli/start-cli-registry-os-version-signer.1 b/core/man/start-cli/start-cli-registry-os-version-signer.1 new file mode 100644 index 000000000..764c97c94 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version-signer.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version-signer 1 "signer " +.SH NAME +start\-cli\-registry\-os\-version\-signer \- Add, remove, and list version signers +.SH SYNOPSIS +\fBstart\-cli registry os version signer\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Add, remove, and list version signers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-os\-version\-signer\-add(1) +Add version signer +.TP +start\-cli\-registry\-os\-version\-signer\-list(1) +List version signers +.TP +start\-cli\-registry\-os\-version\-signer\-remove(1) +Remove version signer diff --git a/core/man/start-cli/start-cli-registry-os-version.1 b/core/man/start-cli/start-cli-registry-os-version.1 new file mode 100644 index 000000000..b205e9db0 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os-version.1 @@ -0,0 +1,26 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os-version 1 "version " +.SH NAME +start\-cli\-registry\-os\-version \- Commands to add, remove, or list versions or version signers +.SH SYNOPSIS +\fBstart\-cli registry os version\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to add, remove, or list versions or version signers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-os\-version\-add(1) +Add OS version +.TP +start\-cli\-registry\-os\-version\-get(1) +Get OS versions info +.TP +start\-cli\-registry\-os\-version\-remove(1) +Remove OS version +.TP +start\-cli\-registry\-os\-version\-signer(1) +Add, remove, and list version signers diff --git a/core/man/start-cli/start-cli-registry-os.1 b/core/man/start-cli/start-cli-registry-os.1 new file mode 100644 index 000000000..1a60e9915 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-os.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-os 1 "os " +.SH NAME +start\-cli\-registry\-os \- Commands related to OS assets and versions +.SH SYNOPSIS +\fBstart\-cli registry os\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to OS assets and versions +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-os\-asset(1) +Commands to add, sign, or get registry assets +.TP +start\-cli\-registry\-os\-index(1) +List OS versions index +.TP +start\-cli\-registry\-os\-version(1) +Commands to add, remove, or list versions or version signers diff --git a/core/man/start-cli/start-cli-registry-package-add-mirror.1 b/core/man/start-cli/start-cli-registry-package-add-mirror.1 new file mode 100644 index 000000000..56bb6d474 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-add-mirror.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-add-mirror 1 "add-mirror " +.SH NAME +start\-cli\-registry\-package\-add\-mirror \- Add a mirror for an s9pk +.SH SYNOPSIS +\fBstart\-cli registry package add\-mirror\fR [\fB\-\-no\-verify\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIFILE\fR> <\fIURL\fR> +.SH DESCRIPTION +Add a mirror for an s9pk +.SH OPTIONS +.TP +\fB\-\-no\-verify\fR +Skip signature verification +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFILE\fR> +Path to s9pk package file +.TP +<\fIURL\fR> +URL of the mirror diff --git a/core/man/start-cli/start-cli-registry-package-add.1 b/core/man/start-cli/start-cli-registry-package-add.1 new file mode 100644 index 000000000..b2f7f2538 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-add.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-add 1 "add " +.SH NAME +start\-cli\-registry\-package\-add \- Add package to registry index +.SH SYNOPSIS +\fBstart\-cli registry package add\fR [\fB\-\-url\fR] [\fB\-\-no\-verify\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIFILE\fR> +.SH DESCRIPTION +Add package to registry index +.SH OPTIONS +.TP +\fB\-\-url\fR \fI\fR +URL of the package +.TP +\fB\-\-no\-verify\fR +Skip signature verification +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFILE\fR> +Path to s9pk package file diff --git a/core/man/start-cli/start-cli-registry-package-category-add-package.1 b/core/man/start-cli/start-cli-registry-package-category-add-package.1 new file mode 100644 index 000000000..4d28f3d2f --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-category-add-package.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-category-add-package 1 "add-package " +.SH NAME +start\-cli\-registry\-package\-category\-add\-package \- Add a package to a category +.SH SYNOPSIS +\fBstart\-cli registry package category add\-package\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fIPACKAGE\fR> +.SH DESCRIPTION +Add a package to a category +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> + +.TP +<\fIPACKAGE\fR> + diff --git a/core/man/start-cli/start-cli-registry-package-category-add.1 b/core/man/start-cli/start-cli-registry-package-category-add.1 new file mode 100644 index 000000000..f50e87972 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-category-add.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-category-add 1 "add " +.SH NAME +start\-cli\-registry\-package\-category\-add \- Add a category to the registry +.SH SYNOPSIS +\fBstart\-cli registry package category add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fINAME\fR> +.SH DESCRIPTION +Add a category to the registry +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> + +.TP +<\fINAME\fR> + diff --git a/core/man/start-cli/start-cli-registry-package-category-list.1 b/core/man/start-cli/start-cli-registry-package-category-list.1 new file mode 100644 index 000000000..2e53a90b4 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-category-list.1 @@ -0,0 +1,15 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-category-list 1 "list " +.SH NAME +start\-cli\-registry\-package\-category\-list +.SH SYNOPSIS +\fBstart\-cli registry package category list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-package-category-remove-package.1 b/core/man/start-cli/start-cli-registry-package-category-remove-package.1 new file mode 100644 index 000000000..31bb9e272 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-category-remove-package.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-category-remove-package 1 "remove-package " +.SH NAME +start\-cli\-registry\-package\-category\-remove\-package \- Remove package from category +.SH SYNOPSIS +\fBstart\-cli registry package category remove\-package\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fIPACKAGE\fR> +.SH DESCRIPTION +Remove package from category +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> + +.TP +<\fIPACKAGE\fR> + diff --git a/core/man/start-cli/start-cli-registry-package-category-remove.1 b/core/man/start-cli/start-cli-registry-package-category-remove.1 new file mode 100644 index 000000000..ee83ef7c2 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-category-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-category-remove 1 "remove " +.SH NAME +start\-cli\-registry\-package\-category\-remove \- Remove category from registry +.SH SYNOPSIS +\fBstart\-cli registry package category remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Remove category from registry +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> + diff --git a/core/man/start-cli/start-cli-registry-package-category.1 b/core/man/start-cli/start-cli-registry-package-category.1 new file mode 100644 index 000000000..f4304c19b --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-category.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-category 1 "category " +.SH NAME +start\-cli\-registry\-package\-category \- Update categories in registry +.SH SYNOPSIS +\fBstart\-cli registry package category\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Update categories in registry +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-package\-category\-add(1) +Add a category to the registry +.TP +start\-cli\-registry\-package\-category\-add\-package(1) +Add a package to a category +.TP +start\-cli\-registry\-package\-category\-list(1) +.TP +start\-cli\-registry\-package\-category\-remove(1) +Remove category from registry +.TP +start\-cli\-registry\-package\-category\-remove\-package(1) +Remove package from category diff --git a/core/man/start-cli/start-cli-registry-package-download.1 b/core/man/start-cli/start-cli-registry-package-download.1 new file mode 100644 index 000000000..a229b85ad --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-download.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-download 1 "download " +.SH NAME +start\-cli\-registry\-package\-download \- Download s9pk package +.SH SYNOPSIS +\fBstart\-cli registry package download\fR [\fB\-v\fR|\fB\-\-target\-version\fR] [\fB\-d\fR|\fB\-\-dest\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Download s9pk package +.SH OPTIONS +.TP +\fB\-v\fR, \fB\-\-target\-version\fR \fI\fR +Target version range constraint +.TP +\fB\-d\fR, \fB\-\-dest\fR \fI\fR +Destination path for download +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-registry-package-get.1 b/core/man/start-cli/start-cli-registry-package-get.1 new file mode 100644 index 000000000..fa176e313 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-get.1 @@ -0,0 +1,40 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-get 1 "get " +.SH NAME +start\-cli\-registry\-package\-get \- List installation candidates +.SH SYNOPSIS +\fBstart\-cli registry package get\fR [\fB\-v\fR|\fB\-\-target\-version\fR] [\fB\-\-source\-version\fR] [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIID\fR] [\fIOTHER_VERSIONS\fR] +.SH DESCRIPTION +List installation candidates +.SH OPTIONS +.TP +\fB\-v\fR, \fB\-\-target\-version\fR \fI\fR +Target version range constraint +.TP +\fB\-\-source\-version\fR \fI\fR +Source version to upgrade from +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIID\fR] +Package identifier +.TP +[\fIOTHER_VERSIONS\fR] [default: none] +Detail level for other versions +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +none +.IP \(bu 2 +short +.IP \(bu 2 +full +.RE diff --git a/core/man/start-cli/start-cli-registry-package-index.1 b/core/man/start-cli/start-cli-registry-package-index.1 new file mode 100644 index 000000000..309ba1437 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-index.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-index 1 "index " +.SH NAME +start\-cli\-registry\-package\-index \- List packages and categories +.SH SYNOPSIS +\fBstart\-cli registry package index\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List packages and categories +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-registry-package-remove-mirror.1 b/core/man/start-cli/start-cli-registry-package-remove-mirror.1 new file mode 100644 index 000000000..fcfd1b949 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-remove-mirror.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-remove-mirror 1 "remove-mirror " +.SH NAME +start\-cli\-registry\-package\-remove\-mirror \- Remove mirror package +.SH SYNOPSIS +\fBstart\-cli registry package remove\-mirror\fR <\fB\-\-url\fR> [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fIVERSION\fR> +.SH DESCRIPTION +Remove mirror package +.SH OPTIONS +.TP +\fB\-\-url\fR \fI\fR +URL of the mirror +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier +.TP +<\fIVERSION\fR> +Package version diff --git a/core/man/start-cli/start-cli-registry-package-remove.1 b/core/man/start-cli/start-cli-registry-package-remove.1 new file mode 100644 index 000000000..ca3412740 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-remove.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-remove 1 "remove " +.SH NAME +start\-cli\-registry\-package\-remove \- Remove package from registry +.SH SYNOPSIS +\fBstart\-cli registry package remove\fR [\fB\-\-sighash\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fIVERSION\fR> +.SH DESCRIPTION +Remove package from registry +.SH OPTIONS +.TP +\fB\-\-sighash\fR \fI\fR +Hash for signature verification +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier +.TP +<\fIVERSION\fR> +Package version diff --git a/core/man/start-cli/start-cli-registry-package-signer-add.1 b/core/man/start-cli/start-cli-registry-package-signer-add.1 new file mode 100644 index 000000000..99757c6b1 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-signer-add.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-signer-add 1 "add " +.SH NAME +start\-cli\-registry\-package\-signer\-add \- Add package signer +.SH SYNOPSIS +\fBstart\-cli registry package signer add\fR [\fB\-\-versions\fR] [\fB\-\-merge\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fISIGNER\fR> +.SH DESCRIPTION +Add package signer +.SH OPTIONS +.TP +\fB\-\-versions\fR \fI\fR +Version range constraint +.TP +\fB\-\-merge\fR +Merge with existing version range instead of replacing +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier +.TP +<\fISIGNER\fR> +Signer identifier diff --git a/core/man/start-cli/start-cli-registry-package-signer-list.1 b/core/man/start-cli/start-cli-registry-package-signer-list.1 new file mode 100644 index 000000000..c27a61ba2 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-signer-list.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-signer-list 1 "list " +.SH NAME +start\-cli\-registry\-package\-signer\-list \- List package signers +.SH SYNOPSIS +\fBstart\-cli registry package signer list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +List package signers +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier diff --git a/core/man/start-cli/start-cli-registry-package-signer-remove.1 b/core/man/start-cli/start-cli-registry-package-signer-remove.1 new file mode 100644 index 000000000..ccb973964 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-signer-remove.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-signer-remove 1 "remove " +.SH NAME +start\-cli\-registry\-package\-signer\-remove \- Remove package signer +.SH SYNOPSIS +\fBstart\-cli registry package signer remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fISIGNER\fR> +.SH DESCRIPTION +Remove package signer +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Package identifier +.TP +<\fISIGNER\fR> +Signer identifier diff --git a/core/man/start-cli/start-cli-registry-package-signer.1 b/core/man/start-cli/start-cli-registry-package-signer.1 new file mode 100644 index 000000000..f98bf213e --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package-signer.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package-signer 1 "signer " +.SH NAME +start\-cli\-registry\-package\-signer \- Add, remove, and list package signers +.SH SYNOPSIS +\fBstart\-cli registry package signer\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Add, remove, and list package signers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-package\-signer\-add(1) +Add package signer +.TP +start\-cli\-registry\-package\-signer\-list(1) +List package signers +.TP +start\-cli\-registry\-package\-signer\-remove(1) +Remove package signer diff --git a/core/man/start-cli/start-cli-registry-package.1 b/core/man/start-cli/start-cli-registry-package.1 new file mode 100644 index 000000000..6f8192643 --- /dev/null +++ b/core/man/start-cli/start-cli-registry-package.1 @@ -0,0 +1,41 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry-package 1 "package " +.SH NAME +start\-cli\-registry\-package \- Commands to index, add, or get packages +.SH SYNOPSIS +\fBstart\-cli registry package\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to index, add, or get packages +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-package\-add(1) +Add package to registry index +.TP +start\-cli\-registry\-package\-add\-mirror(1) +Add a mirror for an s9pk +.TP +start\-cli\-registry\-package\-category(1) +Update categories in registry +.TP +start\-cli\-registry\-package\-download(1) +Download s9pk package +.TP +start\-cli\-registry\-package\-get(1) +List installation candidates +.TP +start\-cli\-registry\-package\-index(1) +List packages and categories +.TP +start\-cli\-registry\-package\-remove(1) +Remove package from registry +.TP +start\-cli\-registry\-package\-remove\-mirror(1) +Remove mirror package +.TP +start\-cli\-registry\-package\-signer(1) +Add, remove, and list package signers diff --git a/core/man/start-cli/start-cli-registry.1 b/core/man/start-cli/start-cli-registry.1 new file mode 100644 index 000000000..62952a830 --- /dev/null +++ b/core/man/start-cli/start-cli-registry.1 @@ -0,0 +1,32 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-registry 1 "registry " +.SH NAME +start\-cli\-registry \- Commands related to the registry +.SH SYNOPSIS +\fBstart\-cli registry\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to the registry +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-registry\-admin(1) +Commands to add or list admins or signers +.TP +start\-cli\-registry\-db(1) +Commands to interact with the db i.e. dump and apply +.TP +start\-cli\-registry\-index(1) +List registry info and packages +.TP +start\-cli\-registry\-info(1) +Display registry info +.TP +start\-cli\-registry\-os(1) +Commands related to OS assets and versions +.TP +start\-cli\-registry\-package(1) +Commands to index, add, or get packages diff --git a/core/man/start-cli/start-cli-s9pk-convert.1 b/core/man/start-cli/start-cli-s9pk-convert.1 new file mode 100644 index 000000000..4fb35556b --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-convert.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-convert 1 "convert " +.SH NAME +start\-cli\-s9pk\-convert \- Convert an s9pk from v1 to v2 +.SH SYNOPSIS +\fBstart\-cli s9pk convert\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIS9PK\fR> +.SH DESCRIPTION +Convert an s9pk from v1 to v2 +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIS9PK\fR> +Path to s9pk package file diff --git a/core/man/start-cli/start-cli-s9pk-edit-add-image.1 b/core/man/start-cli/start-cli-s9pk-edit-add-image.1 new file mode 100644 index 000000000..ea08b5084 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-edit-add-image.1 @@ -0,0 +1,37 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-edit-add-image 1 "add-image " +.SH NAME +start\-cli\-s9pk\-edit\-add\-image \- Add image to s9pk +.SH SYNOPSIS +\fBstart\-cli s9pk edit add\-image\fR [\fB\-\-docker\-build\fR] [\fB\-\-dockerfile\fR] [\fB\-\-workdir\fR] [\fB\-\-docker\-tag\fR] [\fB\-\-arch\fR] [\fB\-\-emulate\-missing\-as\fR] [\fB\-\-nvidia\-container\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> +.SH DESCRIPTION +Add image to s9pk +.SH OPTIONS +.TP +\fB\-\-docker\-build\fR +Build Docker image from Dockerfile +.TP +\fB\-\-dockerfile\fR \fI\fR +Path to Dockerfile +.TP +\fB\-\-workdir\fR \fI\fR +Working directory path +.TP +\fB\-\-docker\-tag\fR \fI\fR +Docker image tag to use +.TP +\fB\-\-arch\fR \fI\fR +Filter by CPU architecture +.TP +\fB\-\-emulate\-missing\-as\fR \fI\fR +Emulate missing architecture using this one +.TP +\fB\-\-nvidia\-container\fR +Enable NVIDIA container support +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIID\fR> +Docker image identifier diff --git a/core/man/start-cli/start-cli-s9pk-edit-manifest.1 b/core/man/start-cli/start-cli-s9pk-edit-manifest.1 new file mode 100644 index 000000000..b3146de51 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-edit-manifest.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-edit-manifest 1 "manifest " +.SH NAME +start\-cli\-s9pk\-edit\-manifest \- Edit s9pk manifest +.SH SYNOPSIS +\fBstart\-cli s9pk edit manifest\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIEXPRESSION\fR> +.SH DESCRIPTION +Edit s9pk manifest +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIEXPRESSION\fR> +Database patch expression to apply diff --git a/core/man/start-cli/start-cli-s9pk-edit.1 b/core/man/start-cli/start-cli-s9pk-edit.1 new file mode 100644 index 000000000..fa66f3353 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-edit.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-edit 1 "edit " +.SH NAME +start\-cli\-s9pk\-edit \- Commands to add an image to an s9pk or edit the manifest +.SH SYNOPSIS +\fBstart\-cli s9pk edit\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIS9PK\fR> <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to add an image to an s9pk or edit the manifest +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIS9PK\fR> +Path to s9pk package file +.SH SUBCOMMANDS +.TP +start\-cli\-s9pk\-edit\-add\-image(1) +Add image to s9pk +.TP +start\-cli\-s9pk\-edit\-manifest(1) +Edit s9pk manifest diff --git a/core/man/start-cli/start-cli-s9pk-inspect-cat.1 b/core/man/start-cli/start-cli-s9pk-inspect-cat.1 new file mode 100644 index 000000000..c41b83384 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-inspect-cat.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-inspect-cat 1 "cat " +.SH NAME +start\-cli\-s9pk\-inspect\-cat \- Display file contents from s9pk +.SH SYNOPSIS +\fBstart\-cli s9pk inspect cat\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFILE_PATH\fR> +.SH DESCRIPTION +Display file contents from s9pk +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFILE_PATH\fR> +Path to the file diff --git a/core/man/start-cli/start-cli-s9pk-inspect-commitment.1 b/core/man/start-cli/start-cli-s9pk-inspect-commitment.1 new file mode 100644 index 000000000..15168091a --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-inspect-commitment.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-inspect-commitment 1 "commitment " +.SH NAME +start\-cli\-s9pk\-inspect\-commitment \- about.display\-s9pk\-root\-sighash\-and\-maxsize +.SH SYNOPSIS +\fBstart\-cli s9pk inspect commitment\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +about.display\-s9pk\-root\-sighash\-and\-maxsize +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-s9pk-inspect-file-tree.1 b/core/man/start-cli/start-cli-s9pk-inspect-file-tree.1 new file mode 100644 index 000000000..17247bd49 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-inspect-file-tree.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-inspect-file-tree 1 "file-tree " +.SH NAME +start\-cli\-s9pk\-inspect\-file\-tree \- Display list of paths in s9pk +.SH SYNOPSIS +\fBstart\-cli s9pk inspect file\-tree\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display list of paths in s9pk +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-s9pk-inspect-manifest.1 b/core/man/start-cli/start-cli-s9pk-inspect-manifest.1 new file mode 100644 index 000000000..19bac61fc --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-inspect-manifest.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-inspect-manifest 1 "manifest " +.SH NAME +start\-cli\-s9pk\-inspect\-manifest \- Display the s9pk manifest +.SH SYNOPSIS +\fBstart\-cli s9pk inspect manifest\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display the s9pk manifest +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-s9pk-inspect.1 b/core/man/start-cli/start-cli-s9pk-inspect.1 new file mode 100644 index 000000000..ddd23c1f8 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-inspect.1 @@ -0,0 +1,29 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-inspect 1 "inspect " +.SH NAME +start\-cli\-s9pk\-inspect \- Commands to display file paths, file contents, or manifest +.SH SYNOPSIS +\fBstart\-cli s9pk inspect\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIS9PK\fR> <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to display file paths, file contents, or manifest +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIS9PK\fR> +Path to s9pk package file +.SH SUBCOMMANDS +.TP +start\-cli\-s9pk\-inspect\-cat(1) +Display file contents from s9pk +.TP +start\-cli\-s9pk\-inspect\-commitment(1) +about.display\-s9pk\-root\-sighash\-and\-maxsize +.TP +start\-cli\-s9pk\-inspect\-file\-tree(1) +Display list of paths in s9pk +.TP +start\-cli\-s9pk\-inspect\-manifest(1) +Display the s9pk manifest diff --git a/core/man/start-cli/start-cli-s9pk-list-ingredients.1 b/core/man/start-cli/start-cli-s9pk-list-ingredients.1 new file mode 100644 index 000000000..b2e6de92f --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-list-ingredients.1 @@ -0,0 +1,37 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-list-ingredients 1 "list-ingredients " +.SH NAME +start\-cli\-s9pk\-list\-ingredients \- List paths of package ingredients +.SH SYNOPSIS +\fBstart\-cli s9pk list\-ingredients\fR [\fB\-o\fR|\fB\-\-output\fR] [\fB\-\-javascript\fR] [\fB\-\-icon\fR] [\fB\-\-license\fR] [\fB\-\-assets\fR] [\fB\-\-no\-assets\fR] [\fB\-\-arch\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIPATH\fR] +.SH DESCRIPTION +List paths of package ingredients +.SH OPTIONS +.TP +\fB\-o\fR, \fB\-\-output\fR \fI\fR +Output file path +.TP +\fB\-\-javascript\fR \fI\fR +Path to JavaScript file +.TP +\fB\-\-icon\fR \fI\fR +Path to service icon file +.TP +\fB\-\-license\fR \fI\fR +Path to license file +.TP +\fB\-\-assets\fR \fI\fR +Path to assets directory +.TP +\fB\-\-no\-assets\fR +Build without assets directory +.TP +\fB\-\-arch\fR \fI\fR +Filter by CPU architecture +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIPATH\fR] +Path to input file or directory diff --git a/core/man/start-cli/start-cli-s9pk-pack.1 b/core/man/start-cli/start-cli-s9pk-pack.1 new file mode 100644 index 000000000..c8d956a95 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-pack.1 @@ -0,0 +1,37 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-pack 1 "pack " +.SH NAME +start\-cli\-s9pk\-pack \- Package input files into a valid s9pk +.SH SYNOPSIS +\fBstart\-cli s9pk pack\fR [\fB\-o\fR|\fB\-\-output\fR] [\fB\-\-javascript\fR] [\fB\-\-icon\fR] [\fB\-\-license\fR] [\fB\-\-assets\fR] [\fB\-\-no\-assets\fR] [\fB\-\-arch\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIPATH\fR] +.SH DESCRIPTION +Package input files into a valid s9pk +.SH OPTIONS +.TP +\fB\-o\fR, \fB\-\-output\fR \fI\fR +Output file path +.TP +\fB\-\-javascript\fR \fI\fR +Path to JavaScript file +.TP +\fB\-\-icon\fR \fI\fR +Path to service icon file +.TP +\fB\-\-license\fR \fI\fR +Path to license file +.TP +\fB\-\-assets\fR \fI\fR +Path to assets directory +.TP +\fB\-\-no\-assets\fR +Build without assets directory +.TP +\fB\-\-arch\fR \fI\fR +Filter by CPU architecture +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIPATH\fR] +Path to input file or directory diff --git a/core/man/start-cli/start-cli-s9pk-publish.1 b/core/man/start-cli/start-cli-s9pk-publish.1 new file mode 100644 index 000000000..bfdbde500 --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-publish.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-publish 1 "publish " +.SH NAME +start\-cli\-s9pk\-publish \- Publish s9pk to S3 bucket and index on registry +.SH SYNOPSIS +\fBstart\-cli s9pk publish\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIS9PK\fR> +.SH DESCRIPTION +Publish s9pk to S3 bucket and index on registry +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIS9PK\fR> +Path to s9pk package file diff --git a/core/man/start-cli/start-cli-s9pk-select.1 b/core/man/start-cli/start-cli-s9pk-select.1 new file mode 100644 index 000000000..95a88faea --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk-select.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk-select 1 "select " +.SH NAME +start\-cli\-s9pk\-select \- Select the best compatible s9pk for a target device +.SH SYNOPSIS +\fBstart\-cli s9pk select\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIS9PKS\fR] +.SH DESCRIPTION +Select the best compatible s9pk for a target device +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIS9PKS\fR] +Paths to s9pk package files diff --git a/core/man/start-cli/start-cli-s9pk.1 b/core/man/start-cli/start-cli-s9pk.1 new file mode 100644 index 000000000..6b182760d --- /dev/null +++ b/core/man/start-cli/start-cli-s9pk.1 @@ -0,0 +1,35 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-s9pk 1 "s9pk " +.SH NAME +start\-cli\-s9pk \- Commands for interacting with s9pk files +.SH SYNOPSIS +\fBstart\-cli s9pk\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands for interacting with s9pk files +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-s9pk\-convert(1) +Convert an s9pk from v1 to v2 +.TP +start\-cli\-s9pk\-edit(1) +Commands to add an image to an s9pk or edit the manifest +.TP +start\-cli\-s9pk\-inspect(1) +Commands to display file paths, file contents, or manifest +.TP +start\-cli\-s9pk\-list\-ingredients(1) +List paths of package ingredients +.TP +start\-cli\-s9pk\-pack(1) +Package input files into a valid s9pk +.TP +start\-cli\-s9pk\-publish(1) +Publish s9pk to S3 bucket and index on registry +.TP +start\-cli\-s9pk\-select(1) +Select the best compatible s9pk for a target device diff --git a/core/man/start-cli/start-cli-server-clear-smtp.1 b/core/man/start-cli/start-cli-server-clear-smtp.1 new file mode 100644 index 000000000..d102ff66a --- /dev/null +++ b/core/man/start-cli/start-cli-server-clear-smtp.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-clear-smtp 1 "clear-smtp " +.SH NAME +start\-cli\-server\-clear\-smtp \- Remove system smtp server and credentials +.SH SYNOPSIS +\fBstart\-cli server clear\-smtp\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Remove system smtp server and credentials +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-device-info.1 b/core/man/start-cli/start-cli-server-device-info.1 new file mode 100644 index 000000000..9b5177106 --- /dev/null +++ b/core/man/start-cli/start-cli-server-device-info.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-device-info 1 "device-info " +.SH NAME +start\-cli\-server\-device\-info \- about.get\-device\-info +.SH SYNOPSIS +\fBstart\-cli server device\-info\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +about.get\-device\-info +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-experimental-governor.1 b/core/man/start-cli/start-cli-server-experimental-governor.1 new file mode 100644 index 000000000..cf3743f9d --- /dev/null +++ b/core/man/start-cli/start-cli-server-experimental-governor.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-experimental-governor 1 "governor " +.SH NAME +start\-cli\-server\-experimental\-governor \- Show CPU governors +.SH SYNOPSIS +\fBstart\-cli server experimental governor\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fISET\fR] +.SH DESCRIPTION +Show CPU governors +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fISET\fR] +CPU governor name diff --git a/core/man/start-cli/start-cli-server-experimental-zram.1 b/core/man/start-cli/start-cli-server-experimental-zram.1 new file mode 100644 index 000000000..a3472ac88 --- /dev/null +++ b/core/man/start-cli/start-cli-server-experimental-zram.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-experimental-zram 1 "zram " +.SH NAME +start\-cli\-server\-experimental\-zram \- Enable ZRAM +.SH SYNOPSIS +\fBstart\-cli server experimental zram\fR [\fB\-\-enable\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Enable ZRAM +.SH OPTIONS +.TP +\fB\-\-enable\fR +Enable zram +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-experimental.1 b/core/man/start-cli/start-cli-server-experimental.1 new file mode 100644 index 000000000..f9d023cf8 --- /dev/null +++ b/core/man/start-cli/start-cli-server-experimental.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-experimental 1 "experimental " +.SH NAME +start\-cli\-server\-experimental \- Commands related to configuring experimental options such as zram and cpu governor +.SH SYNOPSIS +\fBstart\-cli server experimental\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to configuring experimental options such as zram and cpu governor +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-experimental\-governor(1) +Show CPU governors +.TP +start\-cli\-server\-experimental\-zram(1) +Enable ZRAM diff --git a/core/man/start-cli/start-cli-server-host-address-domain-private-add.1 b/core/man/start-cli/start-cli-server-host-address-domain-private-add.1 new file mode 100644 index 000000000..296fa09ce --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-domain-private-add.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-domain-private-add 1 "add " +.SH NAME +start\-cli\-server\-host\-address\-domain\-private\-add \- Add a private domain to this host +.SH SYNOPSIS +\fBstart\-cli server host address domain private add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> <\fIGATEWAY\fR> +.SH DESCRIPTION +Add a private domain to this host +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name +.TP +<\fIGATEWAY\fR> + diff --git a/core/man/start-cli/start-cli-server-host-address-domain-private-remove.1 b/core/man/start-cli/start-cli-server-host-address-domain-private-remove.1 new file mode 100644 index 000000000..81e9ae57c --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-domain-private-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-domain-private-remove 1 "remove " +.SH NAME +start\-cli\-server\-host\-address\-domain\-private\-remove \- Remove private domain from host +.SH SYNOPSIS +\fBstart\-cli server host address domain private remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> +.SH DESCRIPTION +Remove private domain from host +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name diff --git a/core/man/start-cli/start-cli-server-host-address-domain-private.1 b/core/man/start-cli/start-cli-server-host-address-domain-private.1 new file mode 100644 index 000000000..dce763f63 --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-domain-private.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-domain-private 1 "private " +.SH NAME +start\-cli\-server\-host\-address\-domain\-private +.SH SYNOPSIS +\fBstart\-cli server host address domain private\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-host\-address\-domain\-private\-add(1) +Add a private domain to this host +.TP +start\-cli\-server\-host\-address\-domain\-private\-remove(1) +Remove private domain from host diff --git a/core/man/start-cli/start-cli-server-host-address-domain-public-add.1 b/core/man/start-cli/start-cli-server-host-address-domain-public-add.1 new file mode 100644 index 000000000..5b31fd5b3 --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-domain-public-add.1 @@ -0,0 +1,25 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-domain-public-add 1 "add " +.SH NAME +start\-cli\-server\-host\-address\-domain\-public\-add \- Add a public domain to this host +.SH SYNOPSIS +\fBstart\-cli server host address domain public add\fR [\fB\-\-acme\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> <\fIGATEWAY\fR> <\fIINTERNAL_PORT\fR> +.SH DESCRIPTION +Add a public domain to this host +.SH OPTIONS +.TP +\fB\-\-acme\fR \fI\fR +ACME provider identifier or url +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name +.TP +<\fIGATEWAY\fR> +Gateway identifier +.TP +<\fIINTERNAL_PORT\fR> +Internal port number diff --git a/core/man/start-cli/start-cli-server-host-address-domain-public-remove.1 b/core/man/start-cli/start-cli-server-host-address-domain-public-remove.1 new file mode 100644 index 000000000..d4e4541aa --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-domain-public-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-domain-public-remove 1 "remove " +.SH NAME +start\-cli\-server\-host\-address\-domain\-public\-remove \- Remove public domain from host +.SH SYNOPSIS +\fBstart\-cli server host address domain public remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR> +.SH DESCRIPTION +Remove public domain from host +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFQDN\fR> +Fully qualified domain name diff --git a/core/man/start-cli/start-cli-server-host-address-domain-public.1 b/core/man/start-cli/start-cli-server-host-address-domain-public.1 new file mode 100644 index 000000000..7a29e2d8a --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-domain-public.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-domain-public 1 "public " +.SH NAME +start\-cli\-server\-host\-address\-domain\-public +.SH SYNOPSIS +\fBstart\-cli server host address domain public\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-host\-address\-domain\-public\-add(1) +Add a public domain to this host +.TP +start\-cli\-server\-host\-address\-domain\-public\-remove(1) +Remove public domain from host diff --git a/core/man/start-cli/start-cli-server-host-address-domain.1 b/core/man/start-cli/start-cli-server-host-address-domain.1 new file mode 100644 index 000000000..278424d07 --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-domain.1 @@ -0,0 +1,17 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-domain 1 "domain " +.SH NAME +start\-cli\-server\-host\-address\-domain +.SH SYNOPSIS +\fBstart\-cli server host address domain\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-host\-address\-domain\-private(1) +.TP +start\-cli\-server\-host\-address\-domain\-public(1) diff --git a/core/man/start-cli/start-cli-server-host-address-list.1 b/core/man/start-cli/start-cli-server-host-address-list.1 new file mode 100644 index 000000000..5d156d809 --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address-list 1 "list " +.SH NAME +start\-cli\-server\-host\-address\-list \- List addresses for a host +.SH SYNOPSIS +\fBstart\-cli server host address list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List addresses for a host +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-host-address.1 b/core/man/start-cli/start-cli-server-host-address.1 new file mode 100644 index 000000000..35f9a5dde --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-address.1 @@ -0,0 +1,18 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-address 1 "address " +.SH NAME +start\-cli\-server\-host\-address +.SH SYNOPSIS +\fBstart\-cli server host address\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-host\-address\-domain(1) +.TP +start\-cli\-server\-host\-address\-list(1) +List addresses for a host diff --git a/core/man/start-cli/start-cli-server-host-binding-list.1 b/core/man/start-cli/start-cli-server-host-binding-list.1 new file mode 100644 index 000000000..40a4aeeed --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-binding-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-binding-list 1 "list " +.SH NAME +start\-cli\-server\-host\-binding\-list \- List bindings for a host +.SH SYNOPSIS +\fBstart\-cli server host binding list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List bindings for a host +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-host-binding-set-address-enabled.1 b/core/man/start-cli/start-cli-server-host-binding-set-address-enabled.1 new file mode 100644 index 000000000..f7e67811f --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-binding-set-address-enabled.1 @@ -0,0 +1,32 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-binding-set-address-enabled 1 "set-address-enabled " +.SH NAME +start\-cli\-server\-host\-binding\-set\-address\-enabled \- about.set\-address\-enabled\-for\-binding +.SH SYNOPSIS +\fBstart\-cli server host binding set\-address\-enabled\fR <\fB\-\-address\fR> [\fB\-\-enabled\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIINTERNAL_PORT\fR> +.SH DESCRIPTION +about.set\-address\-enabled\-for\-binding +.SH OPTIONS +.TP +\fB\-\-address\fR \fI
\fR +help.arg.address +.TP +\fB\-\-enabled\fR \fI\fR +Enable or disable this binding +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +true +.IP \(bu 2 +false +.RE +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIINTERNAL_PORT\fR> +Internal port number diff --git a/core/man/start-cli/start-cli-server-host-binding.1 b/core/man/start-cli/start-cli-server-host-binding.1 new file mode 100644 index 000000000..0a9cd3f44 --- /dev/null +++ b/core/man/start-cli/start-cli-server-host-binding.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host-binding 1 "binding " +.SH NAME +start\-cli\-server\-host\-binding +.SH SYNOPSIS +\fBstart\-cli server host binding\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-host\-binding\-list(1) +List bindings for a host +.TP +start\-cli\-server\-host\-binding\-set\-address\-enabled(1) +about.set\-address\-enabled\-for\-binding diff --git a/core/man/start-cli/start-cli-server-host.1 b/core/man/start-cli/start-cli-server-host.1 new file mode 100644 index 000000000..37e7e7320 --- /dev/null +++ b/core/man/start-cli/start-cli-server-host.1 @@ -0,0 +1,18 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-host 1 "host " +.SH NAME +start\-cli\-server\-host \- Commands for modifying the host for the system ui +.SH SYNOPSIS +\fBstart\-cli server host\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands for modifying the host for the system ui +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-host\-address(1) +.TP +start\-cli\-server\-host\-binding(1) diff --git a/core/man/start-cli/start-cli-server-kernel-logs.1 b/core/man/start-cli/start-cli-server-kernel-logs.1 new file mode 100644 index 000000000..e55e695a6 --- /dev/null +++ b/core/man/start-cli/start-cli-server-kernel-logs.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-kernel-logs 1 "kernel-logs " +.SH NAME +start\-cli\-server\-kernel\-logs \- Display kernel logs +.SH SYNOPSIS +\fBstart\-cli server kernel\-logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display kernel logs +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-logs.1 b/core/man/start-cli/start-cli-server-logs.1 new file mode 100644 index 000000000..944675edb --- /dev/null +++ b/core/man/start-cli/start-cli-server-logs.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-logs 1 "logs " +.SH NAME +start\-cli\-server\-logs \- Display OS logs +.SH SYNOPSIS +\fBstart\-cli server logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display OS logs +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-metrics.1 b/core/man/start-cli/start-cli-server-metrics.1 new file mode 100644 index 000000000..0f15cf788 --- /dev/null +++ b/core/man/start-cli/start-cli-server-metrics.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-metrics 1 "metrics " +.SH NAME +start\-cli\-server\-metrics \- Display server metrics +.SH SYNOPSIS +\fBstart\-cli server metrics\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display server metrics +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-rebuild.1 b/core/man/start-cli/start-cli-server-rebuild.1 new file mode 100644 index 000000000..da1f23442 --- /dev/null +++ b/core/man/start-cli/start-cli-server-rebuild.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-rebuild 1 "rebuild " +.SH NAME +start\-cli\-server\-rebuild \- Teardown and rebuild containers +.SH SYNOPSIS +\fBstart\-cli server rebuild\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Teardown and rebuild containers +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-restart.1 b/core/man/start-cli/start-cli-server-restart.1 new file mode 100644 index 000000000..8ea7cca77 --- /dev/null +++ b/core/man/start-cli/start-cli-server-restart.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-restart 1 "restart " +.SH NAME +start\-cli\-server\-restart \- Restart the server +.SH SYNOPSIS +\fBstart\-cli server restart\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Restart the server +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-set-echoip-urls.1 b/core/man/start-cli/start-cli-server-set-echoip-urls.1 new file mode 100644 index 000000000..f97c53cde --- /dev/null +++ b/core/man/start-cli/start-cli-server-set-echoip-urls.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-set-echoip-urls 1 "set-echoip-urls " +.SH NAME +start\-cli\-server\-set\-echoip\-urls \- Set the Echo IP service URLs +.SH SYNOPSIS +\fBstart\-cli server set\-echoip\-urls\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIURLS\fR] +.SH DESCRIPTION +Set the Echo IP service URLs +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIURLS\fR] +Echo IP service URLs for external IP detection diff --git a/core/man/start-cli/start-cli-server-set-hostname.1 b/core/man/start-cli/start-cli-server-set-hostname.1 new file mode 100644 index 000000000..7500fb159 --- /dev/null +++ b/core/man/start-cli/start-cli-server-set-hostname.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-set-hostname 1 "set-hostname " +.SH NAME +start\-cli\-server\-set\-hostname \- Set the server hostname +.SH SYNOPSIS +\fBstart\-cli server set\-hostname\fR [\fB\-h\fR|\fB\-\-help\fR] [\fINAME\fR] [\fIHOSTNAME\fR] +.SH DESCRIPTION +Set the server hostname +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fINAME\fR] + +.TP +[\fIHOSTNAME\fR] + diff --git a/core/man/start-cli/start-cli-server-set-keyboard.1 b/core/man/start-cli/start-cli-server-set-keyboard.1 new file mode 100644 index 000000000..764b126b9 --- /dev/null +++ b/core/man/start-cli/start-cli-server-set-keyboard.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-set-keyboard 1 "set-keyboard " +.SH NAME +start\-cli\-server\-set\-keyboard \- Set the keyboard layout +.SH SYNOPSIS +\fBstart\-cli server set\-keyboard\fR [\fB\-k\fR|\fB\-\-keymap\fR] [\fB\-m\fR|\fB\-\-model\fR] [\fB\-v\fR|\fB\-\-variant\fR] [\fB\-o\fR|\fB\-\-option\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fILAYOUT\fR> +.SH DESCRIPTION +Set the keyboard layout +.SH OPTIONS +.TP +\fB\-k\fR, \fB\-\-keymap\fR \fI\fR +Console keymap for vconsole +.TP +\fB\-m\fR, \fB\-\-model\fR \fI\fR +Keyboard model +.TP +\fB\-v\fR, \fB\-\-variant\fR \fI\fR +Keyboard layout variant +.TP +\fB\-o\fR, \fB\-\-option\fR \fI\fR +Additional keyboard option +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fILAYOUT\fR> +Keyboard layout code diff --git a/core/man/start-cli/start-cli-server-set-language.1 b/core/man/start-cli/start-cli-server-set-language.1 new file mode 100644 index 000000000..6b75a20bb --- /dev/null +++ b/core/man/start-cli/start-cli-server-set-language.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-set-language 1 "set-language " +.SH NAME +start\-cli\-server\-set\-language \- Set the system language +.SH SYNOPSIS +\fBstart\-cli server set\-language\fR [\fB\-h\fR|\fB\-\-help\fR] <\fILANGUAGE\fR> +.SH DESCRIPTION +Set the system language +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fILANGUAGE\fR> +Language code diff --git a/core/man/start-cli/start-cli-server-set-smtp.1 b/core/man/start-cli/start-cli-server-set-smtp.1 new file mode 100644 index 000000000..d2f8734c2 --- /dev/null +++ b/core/man/start-cli/start-cli-server-set-smtp.1 @@ -0,0 +1,41 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-set-smtp 1 "set-smtp " +.SH NAME +start\-cli\-server\-set\-smtp \- Set SMTP configuration +.SH SYNOPSIS +\fBstart\-cli server set\-smtp\fR <\fB\-\-host\fR> <\fB\-\-port\fR> <\fB\-\-from\fR> <\fB\-\-username\fR> [\fB\-\-password\fR] <\fB\-\-security\fR> [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Set SMTP configuration +.SH OPTIONS +.TP +\fB\-\-host\fR \fI\fR +SMTP server hostname +.TP +\fB\-\-port\fR \fI\fR +SMTP server port +.TP +\fB\-\-from\fR \fI\fR +Email sender address +.TP +\fB\-\-username\fR \fI\fR +SMTP authentication username +.TP +\fB\-\-password\fR \fI\fR +SMTP authentication password +.TP +\fB\-\-security\fR \fI\fR +Connection security mode (starttls or tls) +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +starttls +.IP \(bu 2 +tls +.RE +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-shutdown.1 b/core/man/start-cli/start-cli-server-shutdown.1 new file mode 100644 index 000000000..c3e82d5cc --- /dev/null +++ b/core/man/start-cli/start-cli-server-shutdown.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-shutdown 1 "shutdown " +.SH NAME +start\-cli\-server\-shutdown \- Shutdown the server +.SH SYNOPSIS +\fBstart\-cli server shutdown\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Shutdown the server +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-test-smtp.1 b/core/man/start-cli/start-cli-server-test-smtp.1 new file mode 100644 index 000000000..1e7341079 --- /dev/null +++ b/core/man/start-cli/start-cli-server-test-smtp.1 @@ -0,0 +1,44 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-test-smtp 1 "test-smtp " +.SH NAME +start\-cli\-server\-test\-smtp \- Test SMTP configuration +.SH SYNOPSIS +\fBstart\-cli server test\-smtp\fR <\fB\-\-host\fR> <\fB\-\-port\fR> <\fB\-\-from\fR> <\fB\-\-to\fR> <\fB\-\-username\fR> <\fB\-\-password\fR> <\fB\-\-security\fR> [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Test SMTP configuration +.SH OPTIONS +.TP +\fB\-\-host\fR \fI\fR +SMTP server hostname +.TP +\fB\-\-port\fR \fI\fR +SMTP server port +.TP +\fB\-\-from\fR \fI\fR +Email sender address +.TP +\fB\-\-to\fR \fI\fR +Email recipient address +.TP +\fB\-\-username\fR \fI\fR +SMTP authentication username +.TP +\fB\-\-password\fR \fI\fR +SMTP authentication password +.TP +\fB\-\-security\fR \fI\fR +Connection security mode (starttls or tls) +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +starttls +.IP \(bu 2 +tls +.RE +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-time.1 b/core/man/start-cli/start-cli-server-time.1 new file mode 100644 index 000000000..a19b71993 --- /dev/null +++ b/core/man/start-cli/start-cli-server-time.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-time 1 "time " +.SH NAME +start\-cli\-server\-time \- Display server time and uptime +.SH SYNOPSIS +\fBstart\-cli server time\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display server time and uptime +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-update-firmware.1 b/core/man/start-cli/start-cli-server-update-firmware.1 new file mode 100644 index 000000000..4c463e3ed --- /dev/null +++ b/core/man/start-cli/start-cli-server-update-firmware.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-update-firmware 1 "update-firmware " +.SH NAME +start\-cli\-server\-update\-firmware \- Update firmware +.SH SYNOPSIS +\fBstart\-cli server update\-firmware\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Update firmware +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-server-update.1 b/core/man/start-cli/start-cli-server-update.1 new file mode 100644 index 000000000..4f14b41a4 --- /dev/null +++ b/core/man/start-cli/start-cli-server-update.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server-update 1 "update " +.SH NAME +start\-cli\-server\-update \- Check a given registry for StartOS updates and update if available +.SH SYNOPSIS +\fBstart\-cli server update\fR [\fB\-\-to\fR] [\fB\-\-no\-progress\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIREGISTRY\fR> +.SH DESCRIPTION +Check a given registry for StartOS updates and update if available +.SH OPTIONS +.TP +\fB\-\-to\fR \fI\fR +Target version for update +.TP +\fB\-\-no\-progress\fR +Disable progress display +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIREGISTRY\fR> +URL of the registry diff --git a/core/man/start-cli/start-cli-server.1 b/core/man/start-cli/start-cli-server.1 new file mode 100644 index 000000000..cc076f658 --- /dev/null +++ b/core/man/start-cli/start-cli-server.1 @@ -0,0 +1,71 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-server 1 "server " +.SH NAME +start\-cli\-server \- Commands related to the server i.e. restart, update, and shutdown +.SH SYNOPSIS +\fBstart\-cli server\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to the server i.e. restart, update, and shutdown +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-server\-clear\-smtp(1) +Remove system smtp server and credentials +.TP +start\-cli\-server\-device\-info(1) +about.get\-device\-info +.TP +start\-cli\-server\-experimental(1) +Commands related to configuring experimental options such as zram and cpu governor +.TP +start\-cli\-server\-host(1) +Commands for modifying the host for the system ui +.TP +start\-cli\-server\-kernel\-logs(1) +Display kernel logs +.TP +start\-cli\-server\-logs(1) +Display OS logs +.TP +start\-cli\-server\-metrics(1) +Display server metrics +.TP +start\-cli\-server\-rebuild(1) +Teardown and rebuild containers +.TP +start\-cli\-server\-restart(1) +Restart the server +.TP +start\-cli\-server\-set\-echoip\-urls(1) +Set the Echo IP service URLs +.TP +start\-cli\-server\-set\-hostname(1) +Set the server hostname +.TP +start\-cli\-server\-set\-keyboard(1) +Set the keyboard layout +.TP +start\-cli\-server\-set\-language(1) +Set the system language +.TP +start\-cli\-server\-set\-smtp(1) +Set SMTP configuration +.TP +start\-cli\-server\-shutdown(1) +Shutdown the server +.TP +start\-cli\-server\-test\-smtp(1) +Test SMTP configuration +.TP +start\-cli\-server\-time(1) +Display server time and uptime +.TP +start\-cli\-server\-update(1) +Check a given registry for StartOS updates and update if available +.TP +start\-cli\-server\-update\-firmware(1) +Update firmware diff --git a/core/man/start-cli/start-cli-setup-cifs.1 b/core/man/start-cli/start-cli-setup-cifs.1 new file mode 100644 index 000000000..4cb102d59 --- /dev/null +++ b/core/man/start-cli/start-cli-setup-cifs.1 @@ -0,0 +1,12 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-setup-cifs 1 "cifs " +.SH NAME +start\-cli\-setup\-cifs +.SH SYNOPSIS +\fBstart\-cli setup cifs\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-setup-disk.1 b/core/man/start-cli/start-cli-setup-disk.1 new file mode 100644 index 000000000..7fa73a28b --- /dev/null +++ b/core/man/start-cli/start-cli-setup-disk.1 @@ -0,0 +1,12 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-setup-disk 1 "disk " +.SH NAME +start\-cli\-setup\-disk +.SH SYNOPSIS +\fBstart\-cli setup disk\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-setup-logs.1 b/core/man/start-cli/start-cli-setup-logs.1 new file mode 100644 index 000000000..dc7e28229 --- /dev/null +++ b/core/man/start-cli/start-cli-setup-logs.1 @@ -0,0 +1,28 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-setup-logs 1 "logs " +.SH NAME +start\-cli\-setup\-logs \- Display OS logs +.SH SYNOPSIS +\fBstart\-cli setup logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display OS logs +.SH OPTIONS +.TP +\fB\-l\fR, \fB\-\-limit\fR \fI\fR +Maximum number of log entries +.TP +\fB\-c\fR, \fB\-\-cursor\fR \fI\fR +Start from this cursor position +.TP +\fB\-b\fR, \fB\-\-boot\fR \fI\fR +Filter logs by boot ID +.TP +\fB\-B\fR, \fB\-\-before\fR +Show logs before the cursor position +.TP +\fB\-f\fR, \fB\-\-follow\fR +Follow log output in real\-time +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-setup.1 b/core/man/start-cli/start-cli-setup.1 new file mode 100644 index 000000000..ad19491fd --- /dev/null +++ b/core/man/start-cli/start-cli-setup.1 @@ -0,0 +1,21 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-setup 1 "setup " +.SH NAME +start\-cli\-setup \- Commands related to the initial setup +.SH SYNOPSIS +\fBstart\-cli setup\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands related to the initial setup +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-setup\-cifs(1) +.TP +start\-cli\-setup\-disk(1) +.TP +start\-cli\-setup\-logs(1) +Display OS logs diff --git a/core/man/start-cli/start-cli-ssh-add.1 b/core/man/start-cli/start-cli-ssh-add.1 new file mode 100644 index 000000000..0cb2e46cf --- /dev/null +++ b/core/man/start-cli/start-cli-ssh-add.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-ssh-add 1 "add " +.SH NAME +start\-cli\-ssh\-add \- Add ssh key +.SH SYNOPSIS +\fBstart\-cli ssh add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIKEY\fR> +.SH DESCRIPTION +Add ssh key +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIKEY\fR> +SSH public key diff --git a/core/man/start-cli/start-cli-ssh-list.1 b/core/man/start-cli/start-cli-ssh-list.1 new file mode 100644 index 000000000..9b649e9ff --- /dev/null +++ b/core/man/start-cli/start-cli-ssh-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-ssh-list 1 "list " +.SH NAME +start\-cli\-ssh\-list \- List SSH keys +.SH SYNOPSIS +\fBstart\-cli ssh list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List SSH keys +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-ssh-remove.1 b/core/man/start-cli/start-cli-ssh-remove.1 new file mode 100644 index 000000000..702d6a920 --- /dev/null +++ b/core/man/start-cli/start-cli-ssh-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-ssh-remove 1 "remove " +.SH NAME +start\-cli\-ssh\-remove \- Remove an SSH key +.SH SYNOPSIS +\fBstart\-cli ssh remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIFINGERPRINT\fR> +.SH DESCRIPTION +Remove an SSH key +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIFINGERPRINT\fR> +SSH key fingerprint diff --git a/core/man/start-cli/start-cli-ssh.1 b/core/man/start-cli/start-cli-ssh.1 new file mode 100644 index 000000000..6f10ebc7c --- /dev/null +++ b/core/man/start-cli/start-cli-ssh.1 @@ -0,0 +1,23 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-ssh 1 "ssh " +.SH NAME +start\-cli\-ssh \- Commands for interacting with ssh keys i.e. add, delete, list +.SH SYNOPSIS +\fBstart\-cli ssh\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands for interacting with ssh keys i.e. add, delete, list +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-ssh\-add(1) +Add ssh key +.TP +start\-cli\-ssh\-list(1) +List SSH keys +.TP +start\-cli\-ssh\-remove(1) +Remove an SSH key diff --git a/core/man/start-cli/start-cli-state.1 b/core/man/start-cli/start-cli-state.1 new file mode 100644 index 000000000..39a0872c9 --- /dev/null +++ b/core/man/start-cli/start-cli-state.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-state 1 "state " +.SH NAME +start\-cli\-state \- Display the current api specification +.SH SYNOPSIS +\fBstart\-cli state\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display the current api specification +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-tunnel-auth-get-pubkey.1 b/core/man/start-cli/start-cli-tunnel-auth-get-pubkey.1 new file mode 100644 index 000000000..6eda0cf45 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-get-pubkey.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-get-pubkey 1 "get-pubkey " +.SH NAME +start\-cli\-tunnel\-auth\-get\-pubkey \- Get the public key from the server +.SH SYNOPSIS +\fBstart\-cli tunnel auth get\-pubkey\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Get the public key from the server +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-tunnel-auth-key-add.1 b/core/man/start-cli/start-cli-tunnel-auth-key-add.1 new file mode 100644 index 000000000..12137fabe --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-key-add.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-key-add 1 "add " +.SH NAME +start\-cli\-tunnel\-auth\-key\-add \- Add a new authorized key +.SH SYNOPSIS +\fBstart\-cli tunnel auth key add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fINAME\fR> <\fIKEY\fR> +.SH DESCRIPTION +Add a new authorized key +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fINAME\fR> + +.TP +<\fIKEY\fR> + diff --git a/core/man/start-cli/start-cli-tunnel-auth-key-list.1 b/core/man/start-cli/start-cli-tunnel-auth-key-list.1 new file mode 100644 index 000000000..8026a23f1 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-key-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-key-list 1 "list " +.SH NAME +start\-cli\-tunnel\-auth\-key\-list \- List authorized keys +.SH SYNOPSIS +\fBstart\-cli tunnel auth key list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +List authorized keys +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-tunnel-auth-key-remove.1 b/core/man/start-cli/start-cli-tunnel-auth-key-remove.1 new file mode 100644 index 000000000..7ce90b583 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-key-remove.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-key-remove 1 "remove " +.SH NAME +start\-cli\-tunnel\-auth\-key\-remove \- Remove authorized key +.SH SYNOPSIS +\fBstart\-cli tunnel auth key remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIKEY\fR> +.SH DESCRIPTION +Remove authorized key +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIKEY\fR> + diff --git a/core/man/start-cli/start-cli-tunnel-auth-key.1 b/core/man/start-cli/start-cli-tunnel-auth-key.1 new file mode 100644 index 000000000..c130b60ba --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-key.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-key 1 "key " +.SH NAME +start\-cli\-tunnel\-auth\-key +.SH SYNOPSIS +\fBstart\-cli tunnel auth key\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-tunnel\-auth\-key\-add(1) +Add a new authorized key +.TP +start\-cli\-tunnel\-auth\-key\-list(1) +List authorized keys +.TP +start\-cli\-tunnel\-auth\-key\-remove(1) +Remove authorized key diff --git a/core/man/start-cli/start-cli-tunnel-auth-login.1 b/core/man/start-cli/start-cli-tunnel-auth-login.1 new file mode 100644 index 000000000..51d81780a --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-login.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-login 1 "login " +.SH NAME +start\-cli\-tunnel\-auth\-login \- Login to a new auth session +.SH SYNOPSIS +\fBstart\-cli tunnel auth login\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Login to a new auth session +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-tunnel-auth-logout.1 b/core/man/start-cli/start-cli-tunnel-auth-logout.1 new file mode 100644 index 000000000..ec78cc38f --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-logout.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-logout 1 "logout " +.SH NAME +start\-cli\-tunnel\-auth\-logout \- Logout from current auth session +.SH SYNOPSIS +\fBstart\-cli tunnel auth logout\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISESSION\fR> +.SH DESCRIPTION +Logout from current auth session +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISESSION\fR> + diff --git a/core/man/start-cli/start-cli-tunnel-auth-reset-password.1 b/core/man/start-cli/start-cli-tunnel-auth-reset-password.1 new file mode 100644 index 000000000..34f867dff --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-reset-password.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-reset-password 1 "reset-password " +.SH NAME +start\-cli\-tunnel\-auth\-reset\-password \- Reset user interface password +.SH SYNOPSIS +\fBstart\-cli tunnel auth reset\-password\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Reset user interface password +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-tunnel-auth-session-kill.1 b/core/man/start-cli/start-cli-tunnel-auth-session-kill.1 new file mode 100644 index 000000000..cd0d769db --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-session-kill.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-session-kill 1 "kill " +.SH NAME +start\-cli\-tunnel\-auth\-session\-kill \- Terminate auth sessions +.SH SYNOPSIS +\fBstart\-cli tunnel auth session kill\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIIDS\fR] +.SH DESCRIPTION +Terminate auth sessions +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIIDS\fR] +Session identifiers diff --git a/core/man/start-cli/start-cli-tunnel-auth-session-list.1 b/core/man/start-cli/start-cli-tunnel-auth-session-list.1 new file mode 100644 index 000000000..ddc58143e --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-session-list.1 @@ -0,0 +1,16 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-session-list 1 "list " +.SH NAME +start\-cli\-tunnel\-auth\-session\-list \- Display all auth sessions +.SH SYNOPSIS +\fBstart\-cli tunnel auth session list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Display all auth sessions +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-tunnel-auth-session.1 b/core/man/start-cli/start-cli-tunnel-auth-session.1 new file mode 100644 index 000000000..0b221de32 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-session.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-session 1 "session " +.SH NAME +start\-cli\-tunnel\-auth\-session \- List or kill auth sessions +.SH SYNOPSIS +\fBstart\-cli tunnel auth session\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +List or kill auth sessions +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-tunnel\-auth\-session\-kill(1) +Terminate auth sessions +.TP +start\-cli\-tunnel\-auth\-session\-list(1) +Display all auth sessions diff --git a/core/man/start-cli/start-cli-tunnel-auth-set-password.1 b/core/man/start-cli/start-cli-tunnel-auth-set-password.1 new file mode 100644 index 000000000..01ef0c493 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth-set-password.1 @@ -0,0 +1,13 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth-set-password 1 "set-password " +.SH NAME +start\-cli\-tunnel\-auth\-set\-password \- Set user interface password +.SH SYNOPSIS +\fBstart\-cli tunnel auth set\-password\fR [\fB\-h\fR|\fB\-\-help\fR] +.SH DESCRIPTION +Set user interface password +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help diff --git a/core/man/start-cli/start-cli-tunnel-auth.1 b/core/man/start-cli/start-cli-tunnel-auth.1 new file mode 100644 index 000000000..59aa3f74f --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-auth.1 @@ -0,0 +1,34 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-auth 1 "auth " +.SH NAME +start\-cli\-tunnel\-auth \- Add or remove authorized clients +.SH SYNOPSIS +\fBstart\-cli tunnel auth\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Add or remove authorized clients +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-tunnel\-auth\-get\-pubkey(1) +Get the public key from the server +.TP +start\-cli\-tunnel\-auth\-key(1) +.TP +start\-cli\-tunnel\-auth\-login(1) +Login to a new auth session +.TP +start\-cli\-tunnel\-auth\-logout(1) +Logout from current auth session +.TP +start\-cli\-tunnel\-auth\-reset\-password(1) +Reset user interface password +.TP +start\-cli\-tunnel\-auth\-session(1) +List or kill auth sessions +.TP +start\-cli\-tunnel\-auth\-set\-password(1) +Set user interface password diff --git a/core/man/start-cli/start-cli-tunnel-db-apply.1 b/core/man/start-cli/start-cli-tunnel-db-apply.1 new file mode 100644 index 000000000..28f9b523e --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-db-apply.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-db-apply 1 "apply " +.SH NAME +start\-cli\-tunnel\-db\-apply \- Update a database record +.SH SYNOPSIS +\fBstart\-cli tunnel db apply\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIEXPR\fR> [\fIPATH\fR] +.SH DESCRIPTION +Update a database record +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fIEXPR\fR> +Database patch expression to apply +.TP +[\fIPATH\fR] +Path to the database file diff --git a/core/man/start-cli/start-cli-tunnel-db-dump.1 b/core/man/start-cli/start-cli-tunnel-db-dump.1 new file mode 100644 index 000000000..1b489a495 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-db-dump.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-db-dump 1 "dump " +.SH NAME +start\-cli\-tunnel\-db\-dump \- Filter and query the database, display tables and records +.SH SYNOPSIS +\fBstart\-cli tunnel db dump\fR [\fB\-p\fR|\fB\-\-pointer\fR] [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIPATH\fR] +.SH DESCRIPTION +Filter and query the database, display tables and records +.SH OPTIONS +.TP +\fB\-p\fR, \fB\-\-pointer\fR \fI\fR +JSON pointer to specific value +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +[\fIPATH\fR] +Path to the database file diff --git a/core/man/start-cli/start-cli-tunnel-db.1 b/core/man/start-cli/start-cli-tunnel-db.1 new file mode 100644 index 000000000..f163d0119 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-db.1 @@ -0,0 +1,20 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-db 1 "db " +.SH NAME +start\-cli\-tunnel\-db \- Commands to interact with the db i.e. dump and apply +.SH SYNOPSIS +\fBstart\-cli tunnel db\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Commands to interact with the db i.e. dump and apply +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-tunnel\-db\-apply(1) +Update a database record +.TP +start\-cli\-tunnel\-db\-dump(1) +Filter and query the database, display tables and records diff --git a/core/man/start-cli/start-cli-tunnel-device-add.1 b/core/man/start-cli/start-cli-tunnel-device-add.1 new file mode 100644 index 000000000..7696c1157 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-device-add.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-device-add 1 "add " +.SH NAME +start\-cli\-tunnel\-device\-add \- Add a device to a subnet +.SH SYNOPSIS +\fBstart\-cli tunnel device add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISUBNET\fR> <\fINAME\fR> [\fIIP\fR] +.SH DESCRIPTION +Add a device to a subnet +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISUBNET\fR> + +.TP +<\fINAME\fR> + +.TP +[\fIIP\fR] + diff --git a/core/man/start-cli/start-cli-tunnel-device-list.1 b/core/man/start-cli/start-cli-tunnel-device-list.1 new file mode 100644 index 000000000..f92f38c77 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-device-list.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-device-list 1 "list " +.SH NAME +start\-cli\-tunnel\-device\-list \- List devices in a subnet +.SH SYNOPSIS +\fBstart\-cli tunnel device list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fISUBNET\fR> +.SH DESCRIPTION +List devices in a subnet +.SH OPTIONS +.TP +\fB\-\-format\fR + +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISUBNET\fR> + diff --git a/core/man/start-cli/start-cli-tunnel-device-remove.1 b/core/man/start-cli/start-cli-tunnel-device-remove.1 new file mode 100644 index 000000000..f9e375b3f --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-device-remove.1 @@ -0,0 +1,19 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-device-remove 1 "remove " +.SH NAME +start\-cli\-tunnel\-device\-remove \- Remove device from subnet +.SH SYNOPSIS +\fBstart\-cli tunnel device remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISUBNET\fR> <\fIIP\fR> +.SH DESCRIPTION +Remove device from subnet +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISUBNET\fR> + +.TP +<\fIIP\fR> + diff --git a/core/man/start-cli/start-cli-tunnel-device-show-config.1 b/core/man/start-cli/start-cli-tunnel-device-show-config.1 new file mode 100644 index 000000000..29ca6b371 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-device-show-config.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-device-show-config 1 "show-config " +.SH NAME +start\-cli\-tunnel\-device\-show\-config \- Show WireGuard configuration for device +.SH SYNOPSIS +\fBstart\-cli tunnel device show\-config\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISUBNET\fR> <\fIIP\fR> [\fIWAN_ADDR\fR] +.SH DESCRIPTION +Show WireGuard configuration for device +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +<\fISUBNET\fR> + +.TP +<\fIIP\fR> + +.TP +[\fIWAN_ADDR\fR] + diff --git a/core/man/start-cli/start-cli-tunnel-device.1 b/core/man/start-cli/start-cli-tunnel-device.1 new file mode 100644 index 000000000..f3d469834 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-device.1 @@ -0,0 +1,26 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-device 1 "device " +.SH NAME +start\-cli\-tunnel\-device \- Add, remove, or list devices in subnets +.SH SYNOPSIS +\fBstart\-cli tunnel device\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR> +.SH DESCRIPTION +Add, remove, or list devices in subnets +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.SH SUBCOMMANDS +.TP +start\-cli\-tunnel\-device\-add(1) +Add a device to a subnet +.TP +start\-cli\-tunnel\-device\-list(1) +List devices in a subnet +.TP +start\-cli\-tunnel\-device\-remove(1) +Remove device from subnet +.TP +start\-cli\-tunnel\-device\-show\-config(1) +Show WireGuard configuration for device diff --git a/core/man/start-cli/start-cli-tunnel-port-forward-add.1 b/core/man/start-cli/start-cli-tunnel-port-forward-add.1 new file mode 100644 index 000000000..14e966d87 --- /dev/null +++ b/core/man/start-cli/start-cli-tunnel-port-forward-add.1 @@ -0,0 +1,22 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH start-cli-tunnel-port-forward-add 1 "add " +.SH NAME +start\-cli\-tunnel\-port\-forward\-add \- Add a new port forward +.SH SYNOPSIS +\fBstart\-cli tunnel port\-forward add\fR [\fB\-\-label\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fISOURCE\fR> <\fITARGET\fR> +.SH DESCRIPTION +Add a new port forward +.SH OPTIONS +.TP +\fB\-\-label\fR \fI::Metadata: Visit> + Visit> @@ -1088,7 +1091,7 @@ impl VHostServer { acme_cache, crypto_provider: crypto_provider.clone(), get_provider: GetVHostAcmeProvider(mapping.clone()), - in_progress: Watch::new(BTreeSet::new()), + in_progress: Watch::new(BTreeMap::new()), }), RootCaTlsHandler { db, From f64c5437474c5ddae967656133ec272e40d1cb0c Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 19 Mar 2026 00:13:33 -0600 Subject: [PATCH 15/53] fix: add sudo to prune scripts and truncate b3sum in update-squashfs --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 151f19ee6..2fac06cd0 100644 --- a/Makefile +++ b/Makefile @@ -251,10 +251,10 @@ update-deb: results/$(BASENAME).deb # better than update, but only available fro update-squashfs: results/$(BASENAME).squashfs @if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi - $(eval SQFS_SUM := $(shell b3sum results/$(BASENAME).squashfs)) + $(eval SQFS_SUM := $(shell b3sum results/$(BASENAME).squashfs | head -c 32)) $(eval SQFS_SIZE := $(shell du -s --bytes results/$(BASENAME).squashfs | awk '{print $$1}')) - $(call ssh,'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE)') - $(call ssh,'/usr/lib/startos/scripts/prune-boot') + $(call ssh,'sudo /usr/lib/startos/scripts/prune-images $(SQFS_SIZE)') + $(call ssh,'sudo /usr/lib/startos/scripts/prune-boot') $(call cp,results/$(BASENAME).squashfs,/media/startos/images/next.rootfs) $(call ssh,'sudo CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/upgrade /media/startos/images/next.rootfs') From 3ef99eca8761a33fc1dbc6e5683cfd12da3a71df Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 19 Mar 2026 00:41:48 -0600 Subject: [PATCH 16/53] fix: allow private access to vhost targets on public gateways --- core/src/net/vhost.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/core/src/net/vhost.rs b/core/src/net/vhost.rs index 3e5fae4db..e8b515ac8 100644 --- a/core/src/net/vhost.rs +++ b/core/src/net/vhost.rs @@ -734,19 +734,11 @@ where }; let src = tcp.peer_addr.ip(); - // Private: source is in a known subnet or is a private IP (e.g. VPN on a different VLAN) - let is_public = - !ip_info.subnets.iter().any(|s| s.contains(&src)) && !is_private_ip(src); + let dst = tcp.local_addr.ip(); - if is_public { - self.public.contains(&gw.id) - } else { - // Private: accept if connection arrived on an interface with a matching IP - ip_info - .subnets - .iter() - .any(|s| self.private.contains(&s.addr())) - } + self.public.contains(&gw.id) + || (self.private.contains(&dst) + && (ip_info.subnets.iter().any(|s| s.contains(&src)) || is_private_ip(src))) } fn acme(&self) -> Option<&AcmeProvider> { self.acme.as_ref() From e4b0f56fa7193e8a0d3969ef85f92093077cfb36 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 19 Mar 2026 01:07:23 -0600 Subject: [PATCH 17/53] fix: use tmpfs and lazy unmounts in chroot-and-upgrade --- build/lib/scripts/chroot-and-upgrade | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build/lib/scripts/chroot-and-upgrade b/build/lib/scripts/chroot-and-upgrade index f5dd417aa..580f27681 100755 --- a/build/lib/scripts/chroot-and-upgrade +++ b/build/lib/scripts/chroot-and-upgrade @@ -55,8 +55,8 @@ 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 -t tmpfs tmpfs /media/startos/next/run +mount -t tmpfs tmpfs /media/startos/next/tmp mount --bind /dev /media/startos/next/dev mount -t sysfs sysfs /media/startos/next/sys mount -t proc proc /media/startos/next/proc @@ -79,13 +79,13 @@ if mountpoint /media/startos/next/sys/firmware/efi/efivars 2>&1 > /dev/null; the umount /media/startos/next/sys/firmware/efi/efivars fi -umount /media/startos/next/run -umount /media/startos/next/tmp -umount /media/startos/next/dev -umount /media/startos/next/sys -umount /media/startos/next/proc -umount /media/startos/next/boot -umount /media/startos/next/media/startos/root +umount -l /media/startos/next/run +umount -l /media/startos/next/tmp +umount -l /media/startos/next/dev +umount -l /media/startos/next/sys +umount -l /media/startos/next/proc +umount -l /media/startos/next/boot +umount -l /media/startos/next/media/startos/root if [ "$CHROOT_RES" -eq 0 ]; then From 96dcd126dbaacf2cc57c7cb3bc2f20c4a8fcbbdc Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 19 Mar 2026 01:07:37 -0600 Subject: [PATCH 18/53] feat: support restoring backups from a different server --- core/src/backup/restore.rs | 9 ++++++++- sdk/base/lib/osBindings/RestorePackageParams.ts | 3 ++- .../portal/routes/backups/modals/recover.component.ts | 3 ++- .../routes/system/routes/backups/recover.component.ts | 4 ++-- web/projects/ui/src/app/services/api/api.fixures.ts | 1 + 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/core/src/backup/restore.rs b/core/src/backup/restore.rs index fc850ef8c..b75f6f742 100644 --- a/core/src/backup/restore.rs +++ b/core/src/backup/restore.rs @@ -40,6 +40,8 @@ pub struct RestorePackageParams { pub password: String, #[arg(help = "help.arg.package-ids")] pub ids: Vec, + #[arg(long, help = "help.arg.server-id")] + pub server_id: Option, } // #[command(rename = "restore", display(display_none))] @@ -50,13 +52,18 @@ pub async fn restore_packages_rpc( ids, target_id, password, + server_id, }: RestorePackageParams, ) -> Result<(), Error> { let peek = ctx.db.peek().await; let fs = target_id.load(&peek)?; + let server_id = match server_id { + Some(id) => id, + None => peek.as_public().as_server_info().as_id().de()?, + }; let backup_guard = BackupMountGuard::mount( TmpMountGuard::mount(&fs, ReadWrite).await?, - &peek.as_public().as_server_info().as_id().de()?, + &server_id, &password, ) .await?; diff --git a/sdk/base/lib/osBindings/RestorePackageParams.ts b/sdk/base/lib/osBindings/RestorePackageParams.ts index 545d3e7ec..3a3fea189 100644 --- a/sdk/base/lib/osBindings/RestorePackageParams.ts +++ b/sdk/base/lib/osBindings/RestorePackageParams.ts @@ -3,7 +3,8 @@ import type { BackupTargetId } from './BackupTargetId' import type { PackageId } from './PackageId' export type RestorePackageParams = { - ids: Array targetId: BackupTargetId password: string + ids: Array + serverId: string | null } diff --git a/web/projects/ui/src/app/routes/portal/routes/backups/modals/recover.component.ts b/web/projects/ui/src/app/routes/portal/routes/backups/modals/recover.component.ts index ffeef759e..83c74df8b 100644 --- a/web/projects/ui/src/app/routes/portal/routes/backups/modals/recover.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/backups/modals/recover.component.ts @@ -115,13 +115,14 @@ export class BackupsRecoverModal { const ids = options.filter(({ checked }) => !!checked).map(({ id }) => id) const loader = this.loader.open('Initializing').subscribe() - const { targetId, password } = this.context.data + const { targetId, serverId, password } = this.context.data try { await this.api.restorePackages({ ids, targetId, password, + serverId, }) this.context.$implicit.complete() diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/recover.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/recover.component.ts index 0478166bd..1e7015ba2 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/recover.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/recover.component.ts @@ -149,8 +149,8 @@ export class BackupsRecoverComponent { async restore(options: RecoverOption[]): Promise { const ids = options.filter(({ checked }) => !!checked).map(({ id }) => id) - const { targetId, password } = this.context.data - const params = { ids, targetId, password } + const { targetId, serverId, password } = this.context.data + const params = { ids, targetId, password, serverId } const loader = this.loader.open('Initializing').subscribe() try { diff --git a/web/projects/ui/src/app/services/api/api.fixures.ts b/web/projects/ui/src/app/services/api/api.fixures.ts index 3168326f7..0720fcfa3 100644 --- a/web/projects/ui/src/app/services/api/api.fixures.ts +++ b/web/projects/ui/src/app/services/api/api.fixures.ts @@ -1242,6 +1242,7 @@ export namespace Mock { model: null, vendor: 'SSK', guid: null, + filesystem: null, startOs: { '1234-5678-9876-5432': { hostname: 'adjective-noun', From d7c394ef331203eb0122c328773899d2716cf925 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 19 Mar 2026 01:07:45 -0600 Subject: [PATCH 19/53] chore: update generated TS bindings --- sdk/base/lib/osBindings/BackupTarget.ts | 1 + sdk/base/lib/osBindings/PartitionInfo.ts | 1 + sdk/base/lib/osBindings/WifiInfo.ts | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sdk/base/lib/osBindings/BackupTarget.ts b/sdk/base/lib/osBindings/BackupTarget.ts index 886222570..937322017 100644 --- a/sdk/base/lib/osBindings/BackupTarget.ts +++ b/sdk/base/lib/osBindings/BackupTarget.ts @@ -13,5 +13,6 @@ export type BackupTarget = used: number | null startOs: { [key: string]: StartOsRecoveryInfo } guid: string | null + filesystem: string | null } | ({ type: 'cifs' } & CifsBackupTarget) diff --git a/sdk/base/lib/osBindings/PartitionInfo.ts b/sdk/base/lib/osBindings/PartitionInfo.ts index 777199c3b..ff5ea7e63 100644 --- a/sdk/base/lib/osBindings/PartitionInfo.ts +++ b/sdk/base/lib/osBindings/PartitionInfo.ts @@ -8,4 +8,5 @@ export type PartitionInfo = { used: number | null startOs: { [key: string]: StartOsRecoveryInfo } guid: string | null + filesystem: string | null } diff --git a/sdk/base/lib/osBindings/WifiInfo.ts b/sdk/base/lib/osBindings/WifiInfo.ts index ce9b07e9a..ac25dbf93 100644 --- a/sdk/base/lib/osBindings/WifiInfo.ts +++ b/sdk/base/lib/osBindings/WifiInfo.ts @@ -1,8 +1,9 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { GatewayId } from './GatewayId' export type WifiInfo = { enabled: boolean - interface: string | null + interface: GatewayId | null ssids: Array selected: string | null lastRegion: string | null From 6c72a22178c75853ec0aff187bf5cd62aec03c85 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 19 Mar 2026 11:30:37 -0600 Subject: [PATCH 20/53] SDK beta.62: fix dynamicSelect crash on empty values, add smtpShape - Guard z.union() against empty arrays in dynamicSelect/dynamicMultiselect by falling back to z.string() (fixes zod v4 _zod TypeError) - Add smtpShape: typed zod schema for store file models, replacing smtpInputSpec.validator which caused cross-zod-instance errors - Bump version to 0.4.0-beta.62 Co-Authored-By: Claude Opus 4.6 (1M context) --- sdk/CHANGELOG.md | 11 +++ sdk/base/lib/actions/input/builder/value.ts | 53 +++++------- .../lib/actions/input/inputSpecConstants.ts | 85 +++++++++++++++++++ sdk/package/lib/StartSdk.ts | 2 + sdk/package/package.json | 2 +- 5 files changed, 118 insertions(+), 35 deletions(-) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index f980422b2..9adcecc15 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 0.4.0-beta.62 (2026-03-19) + +### Fixed + +- Fixed `Value.dynamicSelect` and `Value.dynamicMultiselect` crashing with `z.union([])` when `values` is empty (zod v4 compatibility) + +### Added + +- `FileHelper.xml`: file helper for XML files using `fast-xml-parser` +- `smtpShape`: typed zod schema for persisting SMTP selection in store file models, replacing direct use of `smtpInputSpec.validator` which caused cross-zod-instance errors + ## 0.4.0-beta.61 — StartOS v0.4.0-alpha.21 (2026-03-16) ### Fixed diff --git a/sdk/base/lib/actions/input/builder/value.ts b/sdk/base/lib/actions/input/builder/value.ts index e916e9ecf..431466563 100644 --- a/sdk/base/lib/actions/input/builder/value.ts +++ b/sdk/base/lib/actions/input/builder/value.ts @@ -15,6 +15,21 @@ import { _, once } from '../../../util' import { z } from 'zod' import { DeepPartial } from '../../../types' +/** Build a union-of-literals validator from object keys, falling back to z.string() when empty */ +function literalKeysValidator( + values: Record, +): z.ZodType { + const keys = Object.keys(values) + if (keys.length === 0) return z.string() + return z.union( + keys.map((x) => z.literal(x)) as [ + z.ZodLiteral, + z.ZodLiteral, + ...z.ZodLiteral[], + ], + ) +} + /** Zod schema for a file upload result — validates `{ path, commitment: { hash, size } }`. */ export const fileInfoParser = z.object({ path: z.string(), @@ -774,13 +789,7 @@ export class Value< */ immutable?: boolean }) { - const validator = z.union( - Object.keys(a.values).map((x: keyof Values & string) => z.literal(x)) as [ - z.ZodLiteral, - z.ZodLiteral, - ...z.ZodLiteral[], - ], - ) + const validator = literalKeysValidator(a.values) return new Value( () => ({ spec: { @@ -825,15 +834,7 @@ export class Value< immutable: false, ...a, }, - validator: z.union( - Object.keys(a.values).map((x: keyof Values & string) => - z.literal(x), - ) as [ - z.ZodLiteral, - z.ZodLiteral, - ...z.ZodLiteral[], - ], - ), + validator: literalKeysValidator(a.values), } }, z.string(), @@ -891,15 +892,7 @@ export class Value< */ immutable?: boolean }) { - const validator = z.array( - z.union( - Object.keys(a.values).map((x) => z.literal(x)) as [ - z.ZodLiteral, - z.ZodLiteral, - ...z.ZodLiteral[], - ], - ), - ) + const validator = z.array(literalKeysValidator(a.values)) return new Value<(keyof Values & string)[]>( () => ({ spec: { @@ -953,15 +946,7 @@ export class Value< immutable: false, ...a, }, - validator: z.array( - z.union( - Object.keys(a.values).map((x) => z.literal(x)) as [ - z.ZodLiteral, - z.ZodLiteral, - ...z.ZodLiteral[], - ], - ), - ), + validator: z.array(literalKeysValidator(a.values)), } }, z.array(z.string())) } diff --git a/sdk/base/lib/actions/input/inputSpecConstants.ts b/sdk/base/lib/actions/input/inputSpecConstants.ts index 54c7afd7d..f83427049 100644 --- a/sdk/base/lib/actions/input/inputSpecConstants.ts +++ b/sdk/base/lib/actions/input/inputSpecConstants.ts @@ -2,6 +2,7 @@ import { GetSystemSmtp, Patterns } from '../../util' import { InputSpec } from './builder/inputSpec' import { Value } from './builder/value' import { Variants } from './builder/variants' +import { z } from 'zod' const securityVariants = Variants.of({ tls: { @@ -182,3 +183,87 @@ export const smtpInputSpec = Value.dynamicUnion(async ({ effects }) => { variants: smtpVariants, } }, smtpVariants.validator) + +const securityShape = z + .object({ + selection: z.enum(['tls', 'starttls']).catch('tls'), + value: z.object({ port: z.string().catch('465') }).catch({ port: '465' }), + }) + .catch({ selection: 'tls' as const, value: { port: '465' } }) + +const providerShape = z + .object({ + selection: z.string().catch('other'), + value: z + .object({ + host: z.string().catch(''), + from: z.string().catch(''), + username: z.string().catch(''), + password: z.string().nullable().optional().catch(null), + security: securityShape, + }) + .catch({ + host: '', + from: '', + username: '', + password: null, + security: securityShape.parse(undefined), + }), + }) + .catch({ + selection: 'other', + value: { + host: '', + from: '', + username: '', + password: null, + security: securityShape.parse(undefined), + }, + }) + +export type SmtpSelection = + | { selection: 'disabled'; value: Record } + | { selection: 'system'; value: { customFrom?: string | null } } + | { + selection: 'custom' + value: { + provider: { + selection: string + value: { + host: string + from: string + username: string + password?: string | null + security: { + selection: 'tls' | 'starttls' + value: { port: string } + } + } + } + } + } + +/** + * Zod schema for persisting SMTP selection in a store file model. + * Use this instead of `smtpInputSpec.validator` to avoid cross-zod-instance issues. + */ +export const smtpShape: z.ZodCatch> = z + .discriminatedUnion('selection', [ + z.object({ + selection: z.literal('disabled'), + value: z.object({}).catch({}), + }), + z.object({ + selection: z.literal('system'), + value: z + .object({ customFrom: z.string().nullable().optional().catch(null) }) + .catch({ customFrom: null }), + }), + z.object({ + selection: z.literal('custom'), + value: z + .object({ provider: providerShape }) + .catch({ provider: providerShape.parse(undefined) }), + }), + ]) + .catch({ selection: 'disabled' as const, value: {} }) diff --git a/sdk/package/lib/StartSdk.ts b/sdk/package/lib/StartSdk.ts index 6bf925141..6f4e9cd47 100644 --- a/sdk/package/lib/StartSdk.ts +++ b/sdk/package/lib/StartSdk.ts @@ -11,6 +11,7 @@ import * as patterns from '../../base/lib/util/patterns' import { Backups } from './backup/Backups' import { smtpInputSpec, + smtpShape, systemSmtpSpec, customSmtp, smtpProviderVariants, @@ -408,6 +409,7 @@ export class StartSdk { }, inputSpecConstants: { smtpInputSpec, + smtpShape, systemSmtpSpec, customSmtp, smtpProviderVariants, diff --git a/sdk/package/package.json b/sdk/package/package.json index 855389278..182235178 100644 --- a/sdk/package/package.json +++ b/sdk/package/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.61", + "version": "0.4.0-beta.62", "description": "Software development kit to facilitate packaging services for StartOS", "main": "./package/lib/index.js", "types": "./package/lib/index.d.ts", From 97b3b548c0ce7bc41aec378e4e646ef25a805e29 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 19 Mar 2026 11:42:43 -0600 Subject: [PATCH 21/53] fix type --- sdk/base/lib/actions/input/inputSpecConstants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/base/lib/actions/input/inputSpecConstants.ts b/sdk/base/lib/actions/input/inputSpecConstants.ts index f83427049..8fe4eb098 100644 --- a/sdk/base/lib/actions/input/inputSpecConstants.ts +++ b/sdk/base/lib/actions/input/inputSpecConstants.ts @@ -247,7 +247,7 @@ export type SmtpSelection = * Zod schema for persisting SMTP selection in a store file model. * Use this instead of `smtpInputSpec.validator` to avoid cross-zod-instance issues. */ -export const smtpShape: z.ZodCatch> = z +export const smtpShape: z.ZodType = z .discriminatedUnion('selection', [ z.object({ selection: z.literal('disabled'), @@ -266,4 +266,4 @@ export const smtpShape: z.ZodCatch> = z .catch({ provider: providerShape.parse(undefined) }), }), ]) - .catch({ selection: 'disabled' as const, value: {} }) + .catch({ selection: 'disabled' as const, value: {} }) as any From 8fbcf44dec5f5c1ec22796f8488434fcef234071 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 19 Mar 2026 11:54:28 -0600 Subject: [PATCH 22/53] fix --- sdk/base/lib/actions/input/inputSpecConstants.ts | 5 ++++- sdk/package/package-lock.json | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sdk/base/lib/actions/input/inputSpecConstants.ts b/sdk/base/lib/actions/input/inputSpecConstants.ts index 8fe4eb098..c1b6fe49e 100644 --- a/sdk/base/lib/actions/input/inputSpecConstants.ts +++ b/sdk/base/lib/actions/input/inputSpecConstants.ts @@ -247,7 +247,10 @@ export type SmtpSelection = * Zod schema for persisting SMTP selection in a store file model. * Use this instead of `smtpInputSpec.validator` to avoid cross-zod-instance issues. */ -export const smtpShape: z.ZodType = z +export const smtpShape: { + parse(data: unknown): SmtpSelection + _output: SmtpSelection +} = z .discriminatedUnion('selection', [ z.object({ selection: z.literal('disabled'), diff --git a/sdk/package/package-lock.json b/sdk/package/package-lock.json index 6582cae3e..9ce9ef680 100644 --- a/sdk/package/package-lock.json +++ b/sdk/package/package-lock.json @@ -1,12 +1,12 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.61", + "version": "0.4.0-beta.62", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.61", + "version": "0.4.0-beta.62", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", From de9a7e41898899b97276858187b6d32c814f78b8 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 19 Mar 2026 13:38:40 -0600 Subject: [PATCH 23/53] fix types --- sdk/base/lib/actions/input/inputSpecConstants.ts | 5 +---- sdk/package/lib/StartSdk.ts | 2 -- sdk/package/lib/index.ts | 4 ++++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sdk/base/lib/actions/input/inputSpecConstants.ts b/sdk/base/lib/actions/input/inputSpecConstants.ts index c1b6fe49e..8fe4eb098 100644 --- a/sdk/base/lib/actions/input/inputSpecConstants.ts +++ b/sdk/base/lib/actions/input/inputSpecConstants.ts @@ -247,10 +247,7 @@ export type SmtpSelection = * Zod schema for persisting SMTP selection in a store file model. * Use this instead of `smtpInputSpec.validator` to avoid cross-zod-instance issues. */ -export const smtpShape: { - parse(data: unknown): SmtpSelection - _output: SmtpSelection -} = z +export const smtpShape: z.ZodType = z .discriminatedUnion('selection', [ z.object({ selection: z.literal('disabled'), diff --git a/sdk/package/lib/StartSdk.ts b/sdk/package/lib/StartSdk.ts index 6f4e9cd47..6bf925141 100644 --- a/sdk/package/lib/StartSdk.ts +++ b/sdk/package/lib/StartSdk.ts @@ -11,7 +11,6 @@ import * as patterns from '../../base/lib/util/patterns' import { Backups } from './backup/Backups' import { smtpInputSpec, - smtpShape, systemSmtpSpec, customSmtp, smtpProviderVariants, @@ -409,7 +408,6 @@ export class StartSdk { }, inputSpecConstants: { smtpInputSpec, - smtpShape, systemSmtpSpec, customSmtp, smtpProviderVariants, diff --git a/sdk/package/lib/index.ts b/sdk/package/lib/index.ts index 13427fe21..06f99b915 100644 --- a/sdk/package/lib/index.ts +++ b/sdk/package/lib/index.ts @@ -30,6 +30,10 @@ export { SubContainer } from './util/SubContainer' export { StartSdk } from './StartSdk' export { setupManifest, buildManifest } from './manifest/setupManifest' export { FileHelper } from './util/fileHelper' +export { + smtpShape, + type SmtpSelection, +} from '../../base/lib/actions/input/inputSpecConstants' export * as actions from '../../base/lib/actions' export * as backup from './backup' From bb745c43cc99ac2453260f7c2f0a0de38befe27e Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 19 Mar 2026 14:28:04 -0600 Subject: [PATCH 24/53] fix: createTask with undefined input values fails to create task MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: Setting a task input property to undefined (e.g. { prune: undefined }) to express "this key should be deleted" resulted in no task being created. JSON.stringify strips undefined values, so { prune: undefined } serialized as {}, and is_partial_of({}, any_config) always returns true — meaning input-not-matches saw a "match" and never activated the task. Fix (two parts): - SDK: coerce undefined to null in task input values before serialization, so they survive JSON.stringify and reach the Rust backend - Rust: treat null in a partial as matching a missing key in the full config, so tasks correctly deactivate when the key is already absent Assumption: null and undefined/absent are semantically equivalent for StartOS config values. Input specs produce concrete values (strings, numbers, booleans, objects, arrays) — null never appears as a meaningful distinct-from-absent value in real-world configs. Co-Authored-By: Claude Opus 4.6 (1M context) --- core/src/util/serde.rs | 3 ++- sdk/base/lib/actions/index.ts | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/core/src/util/serde.rs b/core/src/util/serde.rs index f5a4e3526..4c45813be 100644 --- a/core/src/util/serde.rs +++ b/core/src/util/serde.rs @@ -1456,7 +1456,8 @@ pub fn is_partial_of(partial: &Value, full: &Value) -> bool { if let Some(v_full) = full.get(k) { is_partial_of(v, v_full) } else { - false + // null in partial matches a missing key in full (both represent absence) + v.is_null() } }), (Value::Array(partial), Value::Array(full)) => partial diff --git a/sdk/base/lib/actions/index.ts b/sdk/base/lib/actions/index.ts index c4568ab1c..606f5b4d6 100644 --- a/sdk/base/lib/actions/index.ts +++ b/sdk/base/lib/actions/index.ts @@ -74,6 +74,18 @@ const _validate: T.Task = {} as TaskOptions & { severity: T.TaskSeverity } +/** Recursively converts undefined values to null so they survive JSON serialization */ +function undefinedToNull(obj: unknown): unknown { + if (obj === undefined) return null + if (obj === null || typeof obj !== 'object') return obj + if (Array.isArray(obj)) return obj.map(undefinedToNull) + const result: Record = {} + for (const [k, v] of Object.entries(obj)) { + result[k] = undefinedToNull(v) + } + return result +} + export const createTask = >(options: { effects: T.Effects packageId: T.PackageId @@ -83,8 +95,13 @@ export const createTask = >(options: { }) => { const request = options.options || {} const actionId = options.action.id + const input = + 'input' in request && request.input + ? { ...request.input, value: undefinedToNull(request.input.value) } + : (request as any).input const req = { ...request, + input, actionId, packageId: options.packageId, action: undefined, From 2999d22d2a71127061968d791312a05c24d65b20 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 19 Mar 2026 14:43:08 -0600 Subject: [PATCH 25/53] fix: RunAction task re-evaluation compared against partial input, not full config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: After running an action (e.g. bitcoin's autoconfig), update_tasks was called with the submitted form input — which for task-triggered actions is filtered to only the task's fields (e.g. {zmqEnabled: true}). Other services' tasks targeting the same action were then compared against this partial via is_partial_of, so any task wanting a field NOT in the submission (e.g. {blocknotify: "curl..."}) would incorrectly become active, even though the full config still satisfied it. This caused a cycling bug: running LND's autoconfig (zmqEnabled) would activate Datum's task (blocknotify), and vice versa, despite the merge correctly preserving both values in the config. Fix: After running an action, fetch the full current config via get_action_input (same as create_task and recheck_tasks already do) and compare tasks against that. The one-liner fix would have been to add a get_action_input call in the RunAction handler. Instead, we extracted eval_action_tasks on ServiceActorSeed — a single method that both RunAction and recheck_tasks now call — because the duplication between these two sites is exactly how this bug happened: recheck_tasks fetched the full config, RunAction didn't, and they silently diverged. Co-Authored-By: Claude Opus 4.6 (1M context) --- core/src/service/action.rs | 64 ++++++++++++++++++++++++++++---------- core/src/service/mod.rs | 27 ++++------------ 2 files changed, 53 insertions(+), 38 deletions(-) diff --git a/core/src/service/action.rs b/core/src/service/action.rs index e3367918f..7694728a0 100644 --- a/core/src/service/action.rs +++ b/core/src/service/action.rs @@ -9,7 +9,7 @@ use crate::db::model::package::{ }; use crate::prelude::*; use crate::rpc_continuations::Guid; -use crate::service::{ProcedureName, Service, ServiceActor}; +use crate::service::{ProcedureName, Service, ServiceActor, ServiceActorSeed}; use crate::util::actor::background::BackgroundJobQueue; use crate::util::actor::{ConflictBuilder, Handler}; use crate::util::serde::is_partial_of; @@ -131,6 +131,51 @@ pub fn update_tasks( critical_activated } +impl ServiceActorSeed { + /// Fetch the current action input and re-evaluate all tasks targeting this action. + /// + /// This is the single source of truth for task re-evaluation. Used both after + /// running an action and during service init (recheck_tasks). + pub(super) async fn eval_action_tasks( + &self, + action_id: &ActionId, + was_run: bool, + ) -> Result<(), Error> { + let package_id = &self.id; + let current_input = self + .persistent_container + .execute::>( + Guid::new(), + ProcedureName::GetActionInput(action_id.clone()), + json!({ "prefill": Value::Null }), + Some(Duration::from_secs(30)), + ) + .await + .log_err() + .ok() + .flatten() + .and_then(|ai| ai.value); + let Some(input) = current_input else { + return Ok(()); + }; + self.ctx + .db + .mutate(|db| { + for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { + if pde.as_tasks_mut().mutate(|tasks| { + Ok(update_tasks(tasks, package_id, action_id, &input, was_run)) + })? { + pde.as_status_info_mut().stop()?; + } + } + Ok(()) + }) + .await + .result?; + Ok(()) + } +} + pub(super) struct RunAction { action_id: ActionId, input: Value, @@ -203,22 +248,7 @@ impl Handler for ServiceActor { ) .await .with_kind(ErrorKind::Action)?; - let package_id = package_id.clone(); - self.0 - .ctx - .db - .mutate(|db| { - for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { - if pde.as_tasks_mut().mutate(|tasks| { - Ok(update_tasks(tasks, &package_id, action_id, &input, true)) - })? { - pde.as_status_info_mut().stop()?; - } - } - Ok(()) - }) - .await - .result?; + self.0.eval_action_tasks(action_id, true).await?; Ok(result) } } diff --git a/core/src/service/mod.rs b/core/src/service/mod.rs index 9fbcfa300..05c6e56ea 100644 --- a/core/src/service/mod.rs +++ b/core/src/service/mod.rs @@ -39,7 +39,6 @@ use crate::lxc::ContainerId; use crate::prelude::*; use crate::rpc_continuations::{Guid, RpcContinuation}; use crate::s9pk::S9pk; -use crate::service::action::update_tasks; use crate::service::rpc::{ExitParams, InitKind}; use crate::service::service_map::InstallProgressHandles; use crate::service::uninstall::cleanup; @@ -238,8 +237,7 @@ impl Service { async fn recheck_tasks(&self) -> Result<(), Error> { let service_id = &self.seed.id; let peek = self.seed.ctx.db.peek().await; - let mut action_input: BTreeMap = BTreeMap::new(); - let tasks: BTreeSet<_> = peek + let action_ids: BTreeSet<_> = peek .as_public() .as_package_data() .as_entries()? @@ -266,29 +264,16 @@ impl Service { .flatten_ok() .map(|a| a.and_then(|a| a)) .try_collect()?; - let procedure_id = Guid::new(); - for action_id in tasks { - if let Some(input) = self - .get_action_input(procedure_id.clone(), action_id.clone(), Value::Null) - .await - .log_err() - .flatten() - .and_then(|i| i.value) - { - action_input.insert(action_id, input); - } + drop(peek); + for action_id in action_ids { + self.seed.eval_action_tasks(&action_id, false).await?; } + // Defensive sweep: stop any package that still has an active critical task. + // This catches tasks that were already active before this init cycle. self.seed .ctx .db .mutate(|db| { - for (action_id, input) in &action_input { - for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { - pde.as_tasks_mut().mutate(|tasks| { - Ok(update_tasks(tasks, service_id, action_id, input, false)) - })?; - } - } for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { if pde .as_tasks() From 56cb3861bceebab83f60f0e5bd5f9067a8bd1d74 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Thu, 19 Mar 2026 18:00:22 -0600 Subject: [PATCH 26/53] fix build --- core/src/service/action.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/service/action.rs b/core/src/service/action.rs index 7694728a0..772f0dfc6 100644 --- a/core/src/service/action.rs +++ b/core/src/service/action.rs @@ -152,7 +152,6 @@ impl ServiceActorSeed { ) .await .log_err() - .ok() .flatten() .and_then(|ai| ai.value); let Some(input) = current_input else { From f41fc750244cb474d148b6bbfe8af3f50d73e54c Mon Sep 17 00:00:00 2001 From: Alex Inkin Date: Fri, 20 Mar 2026 04:18:25 +0400 Subject: [PATCH 27/53] chore: make service icons not round and add wifi lock badge (#3139) * chore: make service icons not round and add wifi lock badge * chore: comments --- .../src/app/routes/portal/portal.component.ts | 46 +++++++++------- .../components/dependencies.component.ts | 2 +- .../services/components/task.component.ts | 2 +- .../services/dashboard/service.component.ts | 22 ++++---- .../services/routes/outlet.component.ts | 9 +++- .../system/routes/wifi/table.component.ts | 53 +++++++++++++------ web/projects/ui/src/styles.scss | 11 ++-- 7 files changed, 93 insertions(+), 52 deletions(-) diff --git a/web/projects/ui/src/app/routes/portal/portal.component.ts b/web/projects/ui/src/app/routes/portal/portal.component.ts index 7d4424f20..91b861124 100644 --- a/web/projects/ui/src/app/routes/portal/portal.component.ts +++ b/web/projects/ui/src/app/routes/portal/portal.component.ts @@ -9,6 +9,7 @@ import { RouterOutlet } from '@angular/router' import { ErrorService } from '@start9labs/shared' import { TuiButton, + TuiCell, TuiIcon, TuiLoader, TuiPopup, @@ -37,24 +38,26 @@ import { HeaderComponent } from './components/header/header.component' @if (update(); as update) { - @if (update === true) { - - Download complete, restart to apply changes - } @else if ( - update.overall && update.overall !== true && update.overall.total - ) { - - Downloading: - {{ getProgress(update.overall.total, update.overall.done) }}% - } @else { - - Calculating download size - } + + @if (update === true) { + + Download complete, restart to apply changes + } @else if ( + update.overall && update.overall !== true && update.overall.total + ) { + + Downloading: + {{ getProgress(update.overall.total, update.overall.done) }}% + } @else { + + Calculating download size + } + @if (update === true) { } @@ -91,6 +94,12 @@ import { HeaderComponent } from './components/header/header.component' filter: none; } } + + [tuiCell] { + padding: 0; + white-space: normal; + text-wrap: balance; + } `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ @@ -104,6 +113,7 @@ import { HeaderComponent } from './components/header/header.component' TuiIcon, TuiButton, TuiPopup, + TuiCell, ], }) export class PortalComponent { diff --git a/web/projects/ui/src/app/routes/portal/routes/services/components/dependencies.component.ts b/web/projects/ui/src/app/routes/portal/routes/services/components/dependencies.component.ts index 384db648a..3eba51ac7 100644 --- a/web/projects/ui/src/app/routes/portal/routes/services/components/dependencies.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/services/components/dependencies.component.ts @@ -23,7 +23,7 @@ import { ToManifestPipe } from '../../../pipes/to-manifest' [queryParams]="services[d.key] ? {} : { search: d.key }" [class.error]="getError(d.key)" > - + - + {{ title() || fallback()?.title }} diff --git a/web/projects/ui/src/app/routes/portal/routes/services/dashboard/service.component.ts b/web/projects/ui/src/app/routes/portal/routes/services/dashboard/service.component.ts index 33e028f28..29158f008 100644 --- a/web/projects/ui/src/app/routes/portal/routes/services/dashboard/service.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/services/dashboard/service.component.ts @@ -6,6 +6,7 @@ import { } from '@angular/core' import { RouterLink } from '@angular/router' import { i18nPipe } from '@start9labs/shared' +import { TuiAvatar } from '@taiga-ui/kit' import { ServiceUptimeComponent } from 'src/app/routes/portal/routes/services/components/uptime.component' import { PkgDependencyErrors } from 'src/app/services/dep-error.service' import { PackageDataEntry } from 'src/app/services/patch-db/data-model' @@ -16,7 +17,9 @@ import { StatusComponent } from './status.component' selector: 'tr[appService]', template: `
} @@ -186,12 +185,7 @@ export class NotificationItemComponent { overflow = false onClick(item: ServerNotification) { - if (this.overflow) { - this.service.viewModal(item, true) - item.seen = true - } else if ([1, 2].includes(item.code)) { - this.service.viewModal(item) - item.seen = true - } + this.service.viewModal(item) + item.seen = true } } diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/authorities/authorities.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/authorities/authorities.component.ts index 590da78ae..d5d6f1bf3 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/authorities/authorities.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/authorities/authorities.component.ts @@ -9,10 +9,20 @@ import { AuthoritiesTableComponent } from './table.component' @Component({ template: ` - - {{ 'Back' | i18n }} - - {{ 'Certificate Authorities' | i18n }} +
+ + {{ 'Back' | i18n }} + + {{ 'Certificate Authorities' | i18n }} + +
diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/backups.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/backups.component.ts index 94e2aeb89..0609ce444 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/backups.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/backups.component.ts @@ -9,13 +9,7 @@ import { toSignal } from '@angular/core/rxjs-interop' import { ActivatedRoute, RouterLink } from '@angular/router' import { DialogService, DocsLinkDirective, i18nPipe } from '@start9labs/shared' import { TuiMapperPipe } from '@taiga-ui/cdk' -import { - TuiButton, - TuiLink, - TuiLoader, - TuiNotification, - TuiTitle, -} from '@taiga-ui/core' +import { TuiButton, TuiLoader, TuiNotification, TuiTitle } from '@taiga-ui/core' import { TuiHeader } from '@taiga-ui/layout' import { PatchDB } from 'patch-db-client' import { @@ -35,12 +29,28 @@ import { BACKUP_RESTORE } from './restore.component' @Component({ template: ` - - {{ 'Back' | i18n }} - - {{ - type === 'create' ? ('Create Backup' | i18n) : ('Restore Backup' | i18n) - }} +
+ + {{ 'Back' | i18n }} + + {{ + type === 'create' + ? ('Create Backup' | i18n) + : ('Restore Backup' | i18n) + }} + +
@@ -51,36 +61,19 @@ import { BACKUP_RESTORE } from './restore.component' ? ('Create Backup' | i18n) : ('Restore Backup' | i18n) }} + -

- @if (type === 'create') { - {{ - 'Back up StartOS and service data by connecting to a device on your local network or a physical drive connected to your server.' - | i18n - }} - - } @else { - {{ - 'Restore StartOS and service data from a device on your local network or a physical drive connected to your server that contains an existing backup.' - | i18n - }} - - } -

@@ -109,30 +102,16 @@ import { BACKUP_RESTORE } from './restore.component' [style.height.rem]="20" /> } @else { -
- {{ - 'A folder on another computer that is connected to the same network as your Start9 server.' - | i18n - }} - -
-
- {{ - 'A physical drive that is plugged directly into your Start9 Server.' - | i18n - }} -
+
+
} } `, + styles: ` + :host-context(tui-root._mobile) [tuiHeader] { + display: none; + } + `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ AsyncPipe, @@ -140,7 +119,6 @@ import { BACKUP_RESTORE } from './restore.component' RouterLink, TuiButton, TuiLoader, - TuiLink, TuiHeader, TuiTitle, TuiNotification, @@ -184,12 +162,22 @@ export default class SystemBackupComponent implements OnInit { } onTarget(target: MappedBackupTarget) { - const component = this.type === 'create' ? BACKUP : BACKUP_RESTORE - const label = - this.type === 'create' - ? 'Select Services to Back Up' - : 'Select server backup' - - this.dialog.openComponent(component, { label, data: target }).subscribe() + if (this.type === 'create') { + this.dialog + .openComponent(BACKUP, { + label: 'Select services', + data: target, + size: 'm', + }) + .subscribe() + } else { + this.dialog + .openComponent(BACKUP_RESTORE, { + label: 'Select server', + data: target, + size: 'l', + }) + .subscribe() + } } } diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/network.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/network.component.ts index b40b5196d..29f99a1b4 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/network.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/network.component.ts @@ -7,8 +7,8 @@ import { import { ActivatedRoute } from '@angular/router' import { DialogService, ErrorService, i18nPipe } from '@start9labs/shared' import { ISB, T } from '@start9labs/start-sdk' -import { TuiButton, TuiIcon } from '@taiga-ui/core' -import { TuiNotificationMiddleService, TuiTooltip } from '@taiga-ui/kit' +import { TuiButton, TuiDataList, TuiDropdown, TuiIcon } from '@taiga-ui/core' +import { TuiNotificationMiddleService } from '@taiga-ui/kit' import { filter } from 'rxjs' import { FormComponent } from 'src/app/routes/portal/components/form.component' import { PlaceholderComponent } from 'src/app/routes/portal/components/placeholder.component' @@ -28,10 +28,14 @@ const ERROR = template: `
{{ 'Network Folders' | i18n }} - - -
@@ -59,24 +63,29 @@ const ERROR =
- @@ -106,7 +115,7 @@ const ERROR = } td:first-child { - width: 13rem; + width: 16rem; } td:last-child { @@ -114,10 +123,6 @@ const ERROR = text-align: right; } - [tuiButton] { - margin-inline-start: auto; - } - span { display: flex; align-items: center; @@ -166,8 +171,9 @@ const ERROR = changeDetection: ChangeDetectionStrategy.OnPush, imports: [ TuiButton, + TuiDataList, + TuiDropdown, TuiIcon, - TuiTooltip, PlaceholderComponent, BackupStatusComponent, TableComponent, @@ -186,6 +192,8 @@ export class BackupNetworkComponent { readonly service = inject(BackupService) readonly networkFolders = output>() + opens: Record = {} + select(target: MappedBackupTarget) { if (!target.entry.mountable) { this.dialog.openAlert(ERROR, { label: 'Unable to connect' }).subscribe() @@ -321,7 +329,6 @@ export class BackupNetworkComponent { ), required: true, default: null, - placeholder: 'My Network Folder', }), password: ISB.Value.text({ name: this.i18n.transform('Password')!, @@ -331,7 +338,6 @@ export class BackupNetworkComponent { required: false, default: null, masked: true, - placeholder: 'My Network Folder', }), }) } diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/physical.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/physical.component.ts index c2abb021e..ded119f6f6 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/physical.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/physical.component.ts @@ -5,9 +5,8 @@ import { output, } from '@angular/core' import { ActivatedRoute } from '@angular/router' -import { ConvertBytesPipe, DialogService, i18nPipe } from '@start9labs/shared' -import { TuiButton, TuiIcon } from '@taiga-ui/core' -import { TuiTooltip } from '@taiga-ui/kit' +import { DialogService, i18nPipe } from '@start9labs/shared' +import { TuiButton } from '@taiga-ui/core' import { PlaceholderComponent } from 'src/app/routes/portal/components/placeholder.component' import { TableComponent } from 'src/app/routes/portal/components/table.component' import { DiskBackupTarget } from 'src/app/services/api/api.types' @@ -19,11 +18,9 @@ import { BackupStatusComponent } from './status.component' template: `
{{ 'Physical Drives' | i18n }} - -
-
- logo + + logo + {{ manifest().title }} @@ -50,13 +53,6 @@ import { StatusComponent } from './status.component' display: none; } - img { - display: block; - height: 2rem; - width: 2rem; - border-radius: 100%; - } - a { color: var(--tui-text-primary); font-weight: bold; @@ -93,7 +89,7 @@ import { StatusComponent } from './status.component' background: none; } - img { + [tuiAvatar] { height: 3rem; width: 3rem; } @@ -141,7 +137,13 @@ import { StatusComponent } from './status.component' } `, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [RouterLink, StatusComponent, ServiceUptimeComponent, i18nPipe], + imports: [ + RouterLink, + StatusComponent, + ServiceUptimeComponent, + i18nPipe, + TuiAvatar, + ], }) export class ServiceComponent { readonly pkg = input.required() diff --git a/web/projects/ui/src/app/routes/portal/routes/services/routes/outlet.component.ts b/web/projects/ui/src/app/routes/portal/routes/services/routes/outlet.component.ts index 31380252c..ab81e3ec4 100644 --- a/web/projects/ui/src/app/routes/portal/routes/services/routes/outlet.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/services/routes/outlet.component.ts @@ -33,14 +33,19 @@ import { getManifest } from 'src/app/utils/get-package-data' {{ 'Back' | i18n }} - + {{ manifest()?.title }}
- + From 2fd674eca85282f099eb101c80e5457b67f987f2 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Fri, 20 Mar 2026 08:23:12 -0600 Subject: [PATCH 30/53] bump tor --- build/download-tor-s9pk.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/download-tor-s9pk.sh b/build/download-tor-s9pk.sh index 6a37c82a2..b56b4aef8 100755 --- a/build/download-tor-s9pk.sh +++ b/build/download-tor-s9pk.sh @@ -5,7 +5,7 @@ cd "$(dirname "${BASH_SOURCE[0]}")" set -e ARCH=$1 -VERSION="0.4.9.5:0-beta.0" +VERSION="0.4.9.5:0-beta.1" if [ -z "$ARCH" ]; then >&2 echo "usage: $0 " From b9f2446cee4c68e67b6e026b8bdc5f0a6f59d13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Schj=C3=B8nhaug?= Date: Fri, 20 Mar 2026 15:35:11 +0100 Subject: [PATCH 31/53] Fix Safari hard refresh instructions (#3141) --- .../ui/src/app/components/refresh-alert.component.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/projects/ui/src/app/components/refresh-alert.component.ts b/web/projects/ui/src/app/components/refresh-alert.component.ts index d573f05ae..44550ebd2 100644 --- a/web/projects/ui/src/app/components/refresh-alert.component.ts +++ b/web/projects/ui/src/app/components/refresh-alert.component.ts @@ -48,9 +48,13 @@ import { DataModel } from 'src/app/services/patch-db/data-model' }}
  • - On Mac + On Mac (Chrome/Firefox) : cmd + shift + R
  • +
  • + On Mac (Safari) + : option + cmd + R, or hold option and choose View > Reload Page from Origin +
  • On Linux/Windows : ctrl + shift + R From 2a8d8c7154289e9168e6a8d829c19edcde958dfd Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Fri, 20 Mar 2026 08:37:36 -0600 Subject: [PATCH 32/53] alpha.22 --- core/Cargo.toml | 2 +- core/src/version/mod.rs | 12 ++-- core/src/version/v0_4_0_alpha_22.rs | 37 ++++++++++ sdk/package/lib/StartSdk.ts | 107 ++++++++++++++-------------- web/package-lock.json | 4 +- web/package.json | 2 +- 6 files changed, 103 insertions(+), 61 deletions(-) create mode 100644 core/src/version/v0_4_0_alpha_22.rs diff --git a/core/Cargo.toml b/core/Cargo.toml index 7fe67b2e3..77c189f93 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -15,7 +15,7 @@ license = "MIT" name = "start-os" readme = "README.md" repository = "https://github.com/Start9Labs/start-os" -version = "0.4.0-alpha.21" # VERSION_BUMP +version = "0.4.0-alpha.22" # VERSION_BUMP [lib] name = "startos" diff --git a/core/src/version/mod.rs b/core/src/version/mod.rs index a4585358f..0467b7e13 100644 --- a/core/src/version/mod.rs +++ b/core/src/version/mod.rs @@ -61,8 +61,9 @@ mod v0_4_0_alpha_18; mod v0_4_0_alpha_19; mod v0_4_0_alpha_20; mod v0_4_0_alpha_21; +mod v0_4_0_alpha_22; -pub type Current = v0_4_0_alpha_21::Version; // VERSION_BUMP +pub type Current = v0_4_0_alpha_22::Version; // VERSION_BUMP impl Current { #[instrument(skip(self, db))] @@ -191,7 +192,8 @@ enum Version { V0_4_0_alpha_18(Wrapper), V0_4_0_alpha_19(Wrapper), V0_4_0_alpha_20(Wrapper), - V0_4_0_alpha_21(Wrapper), // VERSION_BUMP + V0_4_0_alpha_21(Wrapper), + V0_4_0_alpha_22(Wrapper), // VERSION_BUMP Other(exver::Version), } @@ -255,7 +257,8 @@ impl Version { Self::V0_4_0_alpha_18(v) => DynVersion(Box::new(v.0)), Self::V0_4_0_alpha_19(v) => DynVersion(Box::new(v.0)), Self::V0_4_0_alpha_20(v) => DynVersion(Box::new(v.0)), - Self::V0_4_0_alpha_21(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP + Self::V0_4_0_alpha_21(v) => DynVersion(Box::new(v.0)), + Self::V0_4_0_alpha_22(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP Self::Other(v) => { return Err(Error::new( eyre!("unknown version {v}"), @@ -311,7 +314,8 @@ impl Version { Version::V0_4_0_alpha_18(Wrapper(x)) => x.semver(), Version::V0_4_0_alpha_19(Wrapper(x)) => x.semver(), Version::V0_4_0_alpha_20(Wrapper(x)) => x.semver(), - Version::V0_4_0_alpha_21(Wrapper(x)) => x.semver(), // VERSION_BUMP + Version::V0_4_0_alpha_21(Wrapper(x)) => x.semver(), + Version::V0_4_0_alpha_22(Wrapper(x)) => x.semver(), // VERSION_BUMP Version::Other(x) => x.clone(), } } diff --git a/core/src/version/v0_4_0_alpha_22.rs b/core/src/version/v0_4_0_alpha_22.rs new file mode 100644 index 000000000..f24ae5c75 --- /dev/null +++ b/core/src/version/v0_4_0_alpha_22.rs @@ -0,0 +1,37 @@ +use exver::{PreReleaseSegment, VersionRange}; + +use super::v0_3_5::V0_3_0_COMPAT; +use super::{VersionT, v0_4_0_alpha_21}; +use crate::prelude::*; + +lazy_static::lazy_static! { + static ref V0_4_0_alpha_22: exver::Version = exver::Version::new( + [0, 4, 0], + [PreReleaseSegment::String("alpha".into()), 22.into()] + ); +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct Version; + +impl VersionT for Version { + type Previous = v0_4_0_alpha_21::Version; + type PreUpRes = (); + + async fn pre_up(self) -> Result { + Ok(()) + } + fn semver(self) -> exver::Version { + V0_4_0_alpha_22.clone() + } + fn compat(self) -> &'static VersionRange { + &V0_3_0_COMPAT + } + #[instrument(skip_all)] + fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result { + Ok(Value::Null) + } + fn down(self, _db: &mut Value) -> Result<(), Error> { + Ok(()) + } +} diff --git a/sdk/package/lib/StartSdk.ts b/sdk/package/lib/StartSdk.ts index 6bf925141..9df7164fa 100644 --- a/sdk/package/lib/StartSdk.ts +++ b/sdk/package/lib/StartSdk.ts @@ -1,75 +1,76 @@ -import { Value } from '../../base/lib/actions/input/builder/value' +import * as fs from 'node:fs/promises' +import * as actions from '../../base/lib/actions' import { InputSpec } from '../../base/lib/actions/input/builder/inputSpec' +import { List } from '../../base/lib/actions/input/builder/list' +import { Value } from '../../base/lib/actions/input/builder/value' import { Variants } from '../../base/lib/actions/input/builder/variants' +import { + customSmtp, + smtpInputSpec, + smtpProviderVariants, + systemSmtpSpec, +} from '../../base/lib/actions/input/inputSpecConstants' import { Action, ActionInfo, Actions, + MaybeFn, + Run, } from '../../base/lib/actions/setupActions' -import { ServiceInterfaceType, Effects } from '../../base/lib/types' -import * as patterns from '../../base/lib/util/patterns' -import { Backups } from './backup/Backups' import { - smtpInputSpec, - systemSmtpSpec, - customSmtp, - smtpProviderVariants, -} from '../../base/lib/actions/input/inputSpecConstants' -import { Daemon, Daemons } from './mainFn/Daemons' -import { checkPortListening } from './health/checkFns/checkPortListening' -import { checkWebUrl, runHealthScript } from './health/checkFns' -import { List } from '../../base/lib/actions/input/builder/list' -import { SetupBackupsParams, setupBackups } from './backup/setupBackups' -import { setupMain } from './mainFn' -import { defaultTrigger } from './trigger/defaultTrigger' -import { changeOnFirstSuccess, cooldownTrigger } from './trigger' -import { setupServiceInterfaces } from '../../base/lib/interfaces/setupInterfaces' -import { setupExportedUrls } from '../../base/lib/interfaces/setupExportedUrls' -import { successFailure } from './trigger/successFailure' + CheckDependencies, + checkDependencies, +} from '../../base/lib/dependencies/dependencies' +import { setupDependencies } from '../../base/lib/dependencies/setupDependencies' +import { testTypeVersion } from '../../base/lib/exver' +import { + setupInit, + setupOnInit, + setupOnUninit, + setupUninit, +} from '../../base/lib/inits' import { MultiHost, Scheme } from '../../base/lib/interfaces/Host' import { ServiceInterfaceBuilder } from '../../base/lib/interfaces/ServiceInterfaceBuilder' -import { GetOutboundGateway, GetSystemSmtp } from './util' -import { nullIfEmpty } from './util' -import { getServiceInterface, getServiceInterfaces } from './util' +import { setupExportedUrls } from '../../base/lib/interfaces/setupExportedUrls' +import { setupServiceInterfaces } from '../../base/lib/interfaces/setupInterfaces' +import * as T from '../../base/lib/types' +import { Effects, ServiceInterfaceType } from '../../base/lib/types' +import { GetContainerIp } from '../../base/lib/util/GetContainerIp' +import { GetStatus } from '../../base/lib/util/GetStatus' +import { getOwnServiceInterface } from '../../base/lib/util/getServiceInterface' +import { getOwnServiceInterfaces } from '../../base/lib/util/getServiceInterfaces' +import * as patterns from '../../base/lib/util/patterns' +import { Backups } from './backup/Backups' +import { SetupBackupsParams, setupBackups } from './backup/setupBackups' +import { checkWebUrl, runHealthScript } from './health/checkFns' +import { checkPortListening } from './health/checkFns/checkPortListening' +import { setupMain } from './mainFn' +import { Daemon, Daemons } from './mainFn/Daemons' +import { Mounts } from './mainFn/Mounts' +import { changeOnFirstSuccess, cooldownTrigger } from './trigger' +import { defaultTrigger } from './trigger/defaultTrigger' +import { successFailure } from './trigger/successFailure' +import { + GetOutboundGateway, + GetSslCertificate, + GetSystemSmtp, + getServiceInterface, + getServiceInterfaces, + getServiceManifest, + nullIfEmpty, + splitCommand, +} from './util' import { CommandOptions, ExitError, SubContainer, SubContainerOwned, } from './util/SubContainer' -import { splitCommand } from './util' -import { Mounts } from './mainFn/Mounts' -import { setupDependencies } from '../../base/lib/dependencies/setupDependencies' -import * as T from '../../base/lib/types' -import { testTypeVersion } from '../../base/lib/exver' -import { - CheckDependencies, - checkDependencies, -} from '../../base/lib/dependencies/dependencies' -import { GetSslCertificate, getServiceManifest } from './util' +import { createVolumes } from './util/Volume' import { getDataVersion, setDataVersion } from './version' -import { MaybeFn } from '../../base/lib/actions/setupActions' -import { GetInput } from '../../base/lib/actions/setupActions' -import { Run } from '../../base/lib/actions/setupActions' -import * as actions from '../../base/lib/actions' -import * as fs from 'node:fs/promises' -import { - setupInit, - setupUninit, - setupOnInit, - setupOnUninit, -} from '../../base/lib/inits' -import { GetContainerIp } from '../../base/lib/util/GetContainerIp' -import { GetStatus } from '../../base/lib/util/GetStatus' -import { - getOwnServiceInterface, - ServiceInterfaceFilled, -} from '../../base/lib/util/getServiceInterface' -import { getOwnServiceInterfaces } from '../../base/lib/util/getServiceInterfaces' -import { Volumes, createVolumes } from './util/Volume' /** The minimum StartOS version required by this SDK release */ -export const OSVersion = testTypeVersion('0.4.0-alpha.21') +export const OSVersion = testTypeVersion('0.4.0-alpha.22') // prettier-ignore type AnyNeverCond = diff --git a/web/package-lock.json b/web/package-lock.json index 8757e3e75..5ebaa3e9d 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "startos-ui", - "version": "0.4.0-alpha.21", + "version": "0.4.0-alpha.22", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "startos-ui", - "version": "0.4.0-alpha.21", + "version": "0.4.0-alpha.22", "license": "MIT", "dependencies": { "@angular/cdk": "^21.2.1", diff --git a/web/package.json b/web/package.json index 8aa0e0799..ea43c169a 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "startos-ui", - "version": "0.4.0-alpha.21", + "version": "0.4.0-alpha.22", "author": "Start9 Labs, Inc", "homepage": "https://start9.com/", "license": "MIT", From 0549c7c0ef040de09cc8b1a9c94f1c2e49c83001 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Fri, 20 Mar 2026 08:50:54 -0600 Subject: [PATCH 33/53] fix build --- core/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Cargo.lock b/core/Cargo.lock index 43b086318..4b077419a 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -6439,7 +6439,7 @@ dependencies = [ [[package]] name = "start-os" -version = "0.4.0-alpha.21" +version = "0.4.0-alpha.22" dependencies = [ "aes", "async-acme", From b54f10af5524ef60884c004a900d77d5f8d9b585 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 20 Mar 2026 11:56:53 -0600 Subject: [PATCH 34/53] fix: rsync backup bugs and optimize flags for encrypted CIFS targets - Fix restoreBackup using backupOptions instead of restoreOptions - Add missing await on preRestore/postRestore hooks - Remove -c (checksum) flag that forced full reads on every run - Add --partial to keep partially transferred files on interruption - Add --inplace to avoid temp-file+rename metadata churn - Add --timeout=300 to prevent hangs on stalled mounts --- sdk/package/lib/backup/Backups.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sdk/package/lib/backup/Backups.ts b/sdk/package/lib/backup/Backups.ts index 5acefcb1c..05efb2554 100644 --- a/sdk/package/lib/backup/Backups.ts +++ b/sdk/package/lib/backup/Backups.ts @@ -221,7 +221,7 @@ export class Backups implements InitScript { * @param effects - The effects context */ async restoreBackup(effects: T.Effects) { - this.preRestore(effects as BackupEffects) + await this.preRestore(effects as BackupEffects) for (const item of this.backupSet) { const rsyncResults = await runRsync({ @@ -229,9 +229,9 @@ export class Backups implements InitScript { dstPath: item.dataPath, options: { ...this.options, - ...this.backupOptions, + ...this.restoreOptions, ...item.options, - ...item.backupOptions, + ...item.restoreOptions, }, }) await rsyncResults.wait() @@ -242,7 +242,7 @@ export class Backups implements InitScript { }) .catch((_) => null) if (dataVersion) await effects.setDataVersion({ version: dataVersion }) - this.postRestore(effects as BackupEffects) + await this.postRestore(effects as BackupEffects) return } } @@ -268,7 +268,10 @@ async function runRsync(rsyncOptions: { for (const exclude of options.exclude) { args.push(`--exclude=${exclude}`) } - args.push('-rlptgocAXH') + args.push('-rlptgoAXH') + args.push('--partial') + args.push('--inplace') + args.push('--timeout=300') args.push('--info=progress2') args.push('--no-inc-recursive') args.push(srcPath) From 7335e52ab31a6fd72a453dc2c73925a9279ce08d Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 20 Mar 2026 13:35:24 -0600 Subject: [PATCH 35/53] fix: daemon lifecycle cleanup and error logging improvements - Refactor HealthDaemon to use a tracked session (AbortController + awaitable promise) instead of fire-and-forget health check loops, preventing health checks from running after a service is stopped - Stop health checks before terminating daemon to avoid false crash reports during intentional shutdown - Guard onExit callbacks with AbortSignal to prevent stale session callbacks - Add logErrorOnce utility to deduplicate repeated error logging - Fix SystemForEmbassy.stop() to capture clean promise before deleting ref - Treat SIGTERM (signal 15) as successful exit in subcontainer sync - Fix asError to return original Error instead of wrapping in new Error - Remove unused ExtendedVersion import from Backups.ts --- container-runtime/package-lock.json | 2 +- .../Systems/SystemForEmbassy/index.ts | 15 ++-- core/src/service/effects/subcontainer/sync.rs | 2 +- sdk/base/lib/util/asError.ts | 2 +- sdk/base/lib/util/index.ts | 1 + sdk/base/lib/util/logErrorOnce.ts | 9 +++ sdk/package/lib/backup/Backups.ts | 1 - sdk/package/lib/mainFn/CommandController.ts | 3 +- sdk/package/lib/mainFn/Daemon.ts | 11 +-- sdk/package/lib/mainFn/HealthDaemon.ts | 79 +++++++++++-------- 10 files changed, 73 insertions(+), 52 deletions(-) create mode 100644 sdk/base/lib/util/logErrorOnce.ts diff --git a/container-runtime/package-lock.json b/container-runtime/package-lock.json index e47b4d89a..31478b8f4 100644 --- a/container-runtime/package-lock.json +++ b/container-runtime/package-lock.json @@ -37,7 +37,7 @@ }, "../sdk/dist": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.61", + "version": "0.4.0-beta.62", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", diff --git a/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts b/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts index 10b1d7ddc..1159efccc 100644 --- a/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts +++ b/container-runtime/src/Adapters/Systems/SystemForEmbassy/index.ts @@ -445,15 +445,14 @@ export class SystemForEmbassy implements System { } callCallback(_callback: number, _args: any[]): void {} async stop(): Promise { - const { currentRunning } = this - this.currentRunning?.clean() + const clean = this.currentRunning?.clean({ + timeout: fromDuration( + (this.manifest.main["sigterm-timeout"] as any) || "30s", + ), + }) delete this.currentRunning - if (currentRunning) { - await currentRunning.clean({ - timeout: fromDuration( - (this.manifest.main["sigterm-timeout"] as any) || "30s", - ), - }) + if (clean) { + await clean } } diff --git a/core/src/service/effects/subcontainer/sync.rs b/core/src/service/effects/subcontainer/sync.rs index 3999a0cd9..e37207ced 100644 --- a/core/src/service/effects/subcontainer/sync.rs +++ b/core/src/service/effects/subcontainer/sync.rs @@ -768,7 +768,7 @@ pub fn exec( stderr_thread.map(|t| t.join().unwrap()); if let Some(code) = exit.code() { std::process::exit(code); - } else if exit.success() { + } else if exit.success() || exit.signal() == Some(15) { Ok(()) } else { Err(Error::new( diff --git a/sdk/base/lib/util/asError.ts b/sdk/base/lib/util/asError.ts index dddb4aafe..a9a58dfcb 100644 --- a/sdk/base/lib/util/asError.ts +++ b/sdk/base/lib/util/asError.ts @@ -8,7 +8,7 @@ */ export const asError = (e: unknown) => { if (e instanceof Error) { - return new Error(e as any) + return e } if (typeof e === 'string') { return new Error(`${e}`) diff --git a/sdk/base/lib/util/index.ts b/sdk/base/lib/util/index.ts index 22cf037ba..e807b2280 100644 --- a/sdk/base/lib/util/index.ts +++ b/sdk/base/lib/util/index.ts @@ -32,3 +32,4 @@ export { deepEqual } from './deepEqual' export { AbortedError } from './AbortedError' export * as regexes from './regexes' export { stringFromStdErrOut } from './stringFromStdErrOut' +export { logErrorOnce } from './logErrorOnce' diff --git a/sdk/base/lib/util/logErrorOnce.ts b/sdk/base/lib/util/logErrorOnce.ts new file mode 100644 index 000000000..356c8d42a --- /dev/null +++ b/sdk/base/lib/util/logErrorOnce.ts @@ -0,0 +1,9 @@ +const loggedErrors = new WeakSet() + +export function logErrorOnce(err: unknown) { + if (typeof err === 'object' && err !== null) { + if (loggedErrors.has(err)) return + loggedErrors.add(err) + } + console.error(err) +} diff --git a/sdk/package/lib/backup/Backups.ts b/sdk/package/lib/backup/Backups.ts index 05efb2554..836844d4e 100644 --- a/sdk/package/lib/backup/Backups.ts +++ b/sdk/package/lib/backup/Backups.ts @@ -2,7 +2,6 @@ import * as T from '../../../base/lib/types' import * as child_process from 'child_process' import * as fs from 'fs/promises' import { Affine, asError } from '../util' -import { ExtendedVersion, VersionRange } from '../../../base/lib' import { InitKind, InitScript } from '../../../base/lib/inits' /** Default rsync options used for backup and restore operations */ diff --git a/sdk/package/lib/mainFn/CommandController.ts b/sdk/package/lib/mainFn/CommandController.ts index d8f290aa3..95c2315c7 100644 --- a/sdk/package/lib/mainFn/CommandController.ts +++ b/sdk/package/lib/mainFn/CommandController.ts @@ -7,6 +7,7 @@ import { Drop, splitCommand } from '../util' import * as cp from 'child_process' import * as fs from 'node:fs/promises' import { DaemonCommandType, ExecCommandOptions, ExecFnOptions } from './Daemons' +import { logErrorOnce } from '../../../base/lib/util/logErrorOnce' /** * Low-level controller for a single running process inside a subcontainer (or as a JS function). @@ -220,6 +221,6 @@ export class CommandController< } } onDrop(): void { - this.term().catch(console.error) + this.term().catch(logErrorOnce) } } diff --git a/sdk/package/lib/mainFn/Daemon.ts b/sdk/package/lib/mainFn/Daemon.ts index fcbf1c9cb..5ce08ce85 100644 --- a/sdk/package/lib/mainFn/Daemon.ts +++ b/sdk/package/lib/mainFn/Daemon.ts @@ -1,5 +1,6 @@ import * as T from '../../../base/lib/types' import { asError } from '../../../base/lib/util/asError' +import { logErrorOnce } from '../../../base/lib/util/logErrorOnce' import { Drop } from '../util' import { SubContainer, @@ -64,7 +65,7 @@ export class Daemon< ) const res = new Daemon(subc, startCommand) effects.onLeaveContext(() => { - res.term({ destroySubcontainer: true }).catch((e) => console.error(e)) + res.term({ destroySubcontainer: true }).catch((e) => logErrorOnce(e)) }) return res } @@ -86,7 +87,7 @@ export class Daemon< if (this.commandController) await this.commandController .term({}) - .catch((err) => console.error(err)) + .catch((err) => logErrorOnce(err)) try { this.commandController = await this.startCommand() if (!this.shouldBeRunning) { @@ -97,7 +98,7 @@ export class Daemon< const success = await this.commandController.wait().then( (_) => true, (err) => { - console.error(err) + if (this.shouldBeRunning) logErrorOnce(err) return false }, ) @@ -147,7 +148,7 @@ export class Daemon< this.onExitFns = [] } if (this.exiting) { - await this.exiting.catch(console.error) + await this.exiting.catch(logErrorOnce) if (termOptions?.destroySubcontainer) { await this.subcontainer?.destroy() } @@ -172,6 +173,6 @@ export class Daemon< this.onExitFns.push(fn) } onDrop(): void { - this.term().catch((e) => console.error(asError(e))) + this.term().catch((e) => logErrorOnce(asError(e))) } } diff --git a/sdk/package/lib/mainFn/HealthDaemon.ts b/sdk/package/lib/mainFn/HealthDaemon.ts index e8c194e94..ad3050af5 100644 --- a/sdk/package/lib/mainFn/HealthDaemon.ts +++ b/sdk/package/lib/mainFn/HealthDaemon.ts @@ -4,14 +4,6 @@ import { Ready } from './Daemons' import { Daemon } from './Daemon' import { SetHealth, Effects, SDKManifest } from '../../../base/lib/types' -const oncePromise = () => { - let resolve: (value: T) => void - const promise = new Promise((res) => { - resolve = res - }) - return { resolve: resolve!, promise } -} - export const EXIT_SUCCESS = 'EXIT_SUCCESS' as const /** @@ -29,6 +21,7 @@ export class HealthDaemon { private resolveReady: (() => void) | undefined private resolvedReady: boolean = false private readyPromise: Promise + private session: { abort: AbortController; done: Promise } | null = null constructor( readonly daemon: Daemon | null, readonly dependencies: HealthDaemon[], @@ -54,7 +47,7 @@ export class HealthDaemon { }) { this.healthWatchers = [] this.running = false - this.healthCheckCleanup?.() + await this.stopSession() await this.daemon?.term({ ...termOptions, @@ -77,20 +70,25 @@ export class HealthDaemon { if (newStatus) { console.debug(`Launching ${this.id}...`) - this.setupHealthCheck() + this.startSession() this.daemon?.start() this.started = performance.now() } else { console.debug(`Stopping ${this.id}...`) - this.daemon?.term() - await this.turnOffHealthCheck() + await this.stopSession() + await this.daemon?.term() } } - private healthCheckCleanup: (() => Promise) | null = null - private async turnOffHealthCheck() { - await this.healthCheckCleanup?.() + private async stopSession() { + if (!this.session) return + this.session.abort.abort() + await this.session.done + this.session = null + this.resetReady() + } + private resetReady() { this.resolvedReady = false this.readyPromise = new Promise( (resolve) => @@ -100,8 +98,14 @@ export class HealthDaemon { }), ) } - private async setupHealthCheck() { + + private startSession() { + this.session?.abort.abort() + + const abort = new AbortController() + this.daemon?.onExit((success) => { + if (abort.signal.aborted) return if (success && this.ready === 'EXIT_SUCCESS') { this.setHealth({ result: 'success', message: null }) } else if (!success) { @@ -116,42 +120,49 @@ export class HealthDaemon { }) } }) + + const done = + this.ready === 'EXIT_SUCCESS' + ? Promise.resolve() + : this.runHealthCheckLoop(abort.signal) + + this.session = { abort, done } + } + + private async runHealthCheckLoop(signal: AbortSignal): Promise { if (this.ready === 'EXIT_SUCCESS') return - if (this.healthCheckCleanup) return const trigger = (this.ready.trigger ?? defaultTrigger)(() => ({ lastResult: this._health.result, })) - const { promise: status, resolve: setStatus } = oncePromise<{ - done: true - }>() - const { promise: exited, resolve: setExited } = oncePromise() - new Promise(async () => { - if (this.ready === 'EXIT_SUCCESS') return + const aborted = new Promise<{ done: true }>((resolve) => + signal.addEventListener('abort', () => resolve({ done: true }), { + once: true, + }), + ) + + try { for ( - let res = await Promise.race([status, trigger.next()]); + let res = await Promise.race([aborted, trigger.next()]); !res.done; - res = await Promise.race([status, trigger.next()]) + res = await Promise.race([aborted, trigger.next()]) ) { const response: HealthCheckResult = await Promise.resolve( this.ready.fn(), ).catch((err) => { return { - result: 'failure', + result: 'failure' as const, message: 'message' in err ? err.message : String(err), } }) + if (signal.aborted) break await this.setHealth(response) } - setExited(null) - }).catch((err) => console.error(`Daemon ${this.id} failed: ${err}`)) - - this.healthCheckCleanup = async () => { - setStatus({ done: true }) - await exited - this.healthCheckCleanup = null - return null + } catch (err) { + if (!signal.aborted) { + console.error(`Daemon ${this.id} health check failed: ${err}`) + } } } From 9ff65497a8cbe246b993e8742e12d3bb0af75542 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 20 Mar 2026 14:31:40 -0600 Subject: [PATCH 36/53] fix: replace fire-and-forget restart loop in Daemon with tracked AbortController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Track the restart loop as an awaitable { abort, done } handle - Remove shouldBeRunning flag — signal.aborted serves the same purpose - Remove exiting field — term() awaits command termination inline - Guard start() on loop existence to prevent concurrent restart loops - Make backoff sleep abortable so term() returns immediately - Suppress error logging during intentional termination - Loop clears its own handle in finally block for natural exit (oneshot) --- sdk/package/lib/mainFn/Daemon.ts | 88 +++++++++++++++++++------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/sdk/package/lib/mainFn/Daemon.ts b/sdk/package/lib/mainFn/Daemon.ts index 5ce08ce85..242c5827d 100644 --- a/sdk/package/lib/mainFn/Daemon.ts +++ b/sdk/package/lib/mainFn/Daemon.ts @@ -2,11 +2,7 @@ import * as T from '../../../base/lib/types' import { asError } from '../../../base/lib/util/asError' import { logErrorOnce } from '../../../base/lib/util/logErrorOnce' import { Drop } from '../util' -import { - SubContainer, - SubContainerOwned, - SubContainerRc, -} from '../util/SubContainer' +import { SubContainer, SubContainerRc } from '../util/SubContainer' import { CommandController } from './CommandController' import { DaemonCommandType } from './Daemons' import { Oneshot } from './Oneshot' @@ -28,10 +24,9 @@ export class Daemon< C extends SubContainer | null = SubContainer | null, > extends Drop { private commandController: CommandController | null = null - private shouldBeRunning = false protected exitedSuccess = false - private exiting: Promise | null = null private onExitFns: ((success: boolean) => void)[] = [] + private loop: { abort: AbortController; done: Promise } | null = null protected constructor( private subcontainer: C, private startCommand: () => Promise>, @@ -77,31 +72,38 @@ export class Daemon< * until {@link term} is called. */ async start() { - if (this.commandController) { + if (this.loop) { return } - this.shouldBeRunning = true + const abort = new AbortController() + const done = this.runLoop(abort.signal) + this.loop = { abort, done } + } + + private async runLoop(signal: AbortSignal) { let timeoutCounter = 0 - ;(async () => { - while (this.shouldBeRunning) { - if (this.commandController) - await this.commandController - .term({}) - .catch((err) => logErrorOnce(err)) + try { + while (!signal.aborted) { + if (this.commandController) { + await this.commandController.term({}).catch(logErrorOnce) + this.commandController = null + } try { this.commandController = await this.startCommand() - if (!this.shouldBeRunning) { - // handles race condition if stopped while starting - await this.term() + if (signal.aborted) { + await this.commandController.term({}).catch(logErrorOnce) + this.commandController = null break } const success = await this.commandController.wait().then( (_) => true, (err) => { - if (this.shouldBeRunning) logErrorOnce(err) + if (!signal.aborted) logErrorOnce(err) return false }, ) + this.commandController = null + if (signal.aborted) break for (const fn of this.onExitFns) { try { fn(success) @@ -114,16 +116,28 @@ export class Daemon< break } } catch (e) { - console.error(e) + if (!signal.aborted) console.error(e) } - await new Promise((resolve) => setTimeout(resolve, timeoutCounter)) + if (signal.aborted) break + await new Promise((resolve) => { + const timer = setTimeout(resolve, timeoutCounter) + signal.addEventListener( + 'abort', + () => { + clearTimeout(timer) + resolve() + }, + { once: true }, + ) + }) timeoutCounter += TIMEOUT_INCREMENT_MS timeoutCounter = Math.min(MAX_TIMEOUT_MS, timeoutCounter) } - })().catch((err) => { - console.error(asError(err)) - }) + } finally { + this.loop = null + } } + /** * Terminate the daemon, stopping its underlying command. * @@ -140,19 +154,23 @@ export class Daemon< timeout?: number | undefined destroySubcontainer?: boolean }) { - this.shouldBeRunning = false this.exitedSuccess = false - if (this.commandController) { - this.exiting = this.commandController.term({ ...termOptions }) - this.commandController = null - this.onExitFns = [] + this.onExitFns = [] + + if (this.loop) { + this.loop.abort.abort() } - if (this.exiting) { - await this.exiting.catch(logErrorOnce) - if (termOptions?.destroySubcontainer) { - await this.subcontainer?.destroy() - } - this.exiting = null + + const exiting = this.commandController?.term({ ...termOptions }) + this.commandController = null + if (exiting) await exiting.catch(logErrorOnce) + + if (this.loop) { + await this.loop.done + } + + if (termOptions?.destroySubcontainer) { + await this.subcontainer?.destroy() } } /** Get a reference-counted handle to the daemon's subcontainer, or null if there is none */ From 8bccffcb5c4c1e5921329c3121db127c7f7d801b Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 20 Mar 2026 15:28:30 -0600 Subject: [PATCH 37/53] feat: add --arch flag to `start-cli registry package download` Use the new flag in the image build recipe to download the tor s9pk for the target architecture, replacing the standalone download script. --- Makefile | 6 +----- build/download-tor-s9pk.sh | 15 --------------- build/image-recipe/build.sh | 2 ++ core/locales/i18n.yaml | 7 +++++++ core/src/registry/package/get.rs | 11 +++++++++++ 5 files changed, 21 insertions(+), 20 deletions(-) delete mode 100755 build/download-tor-s9pk.sh diff --git a/Makefile b/Makefile index 2fac06cd0..6ad4b1291 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,7 @@ IMAGE_TYPE=$(shell if [ "$(PLATFORM)" = raspberrypi ]; then echo img; else echo 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 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) -TOR_S9PK := build/lib/tor_$(ARCH).s9pk -BUILD_SRC := $(call ls-files, build/lib) build/lib/depends build/lib/conflicts $(FIRMWARE_ROMS) $(TOR_S9PK) +BUILD_SRC := $(call ls-files, build/lib) build/lib/depends build/lib/conflicts $(FIRMWARE_ROMS) IMAGE_RECIPE_SRC := $(call ls-files, build/image-recipe/) STARTD_SRC := core/startd.service $(BUILD_SRC) CORE_SRC := $(call ls-files, core) $(shell git ls-files --recurse-submodules patch-db) $(GIT_HASH_FILE) @@ -316,9 +315,6 @@ build/lib/depends build/lib/conflicts: $(ENVIRONMENT_FILE) $(PLATFORM_FILE) $(sh $(FIRMWARE_ROMS): build/lib/firmware.json ./build/download-firmware.sh $(PLATFORM_FILE) ./build/download-firmware.sh $(PLATFORM) -$(TOR_S9PK): ./build/download-tor-s9pk.sh - ./build/download-tor-s9pk.sh $(ARCH) - 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/build-startbox.sh touch core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/startbox diff --git a/build/download-tor-s9pk.sh b/build/download-tor-s9pk.sh deleted file mode 100755 index b56b4aef8..000000000 --- a/build/download-tor-s9pk.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -cd "$(dirname "${BASH_SOURCE[0]}")" - -set -e - -ARCH=$1 -VERSION="0.4.9.5:0-beta.1" - -if [ -z "$ARCH" ]; then - >&2 echo "usage: $0 " - exit 1 -fi - -curl --fail -L -o "./lib/tor_${ARCH}.s9pk" "https://s9pks.nyc3.cdn.digitaloceanspaces.com/tor/${VERSION}/tor_${ARCH}.s9pk" diff --git a/build/image-recipe/build.sh b/build/image-recipe/build.sh index 6648e719a..990abfe89 100755 --- a/build/image-recipe/build.sh +++ b/build/image-recipe/build.sh @@ -357,6 +357,8 @@ mkdir -p /media/startos chmod 750 /media/startos chown root:startos /media/startos +start-cli --registry=https://alpha-registry-x.start9.com registry package download tor -d /usr/lib/startos/tor_${QEMU_ARCH}.s9pk -a "${QEMU_ARCH}" + EOF SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}" diff --git a/core/locales/i18n.yaml b/core/locales/i18n.yaml index 46df68d25..cce91b5e5 100644 --- a/core/locales/i18n.yaml +++ b/core/locales/i18n.yaml @@ -2656,6 +2656,13 @@ help.arg.allow-partial-backup: fr_FR: "Laisser le média monté même si backupfs échoue à monter" pl_PL: "Pozostaw nośnik zamontowany nawet jeśli backupfs nie może się zamontować" +help.arg.architecture: + en_US: "Target CPU architecture (e.g. x86_64, aarch64)" + de_DE: "Ziel-CPU-Architektur (z.B. x86_64, aarch64)" + es_ES: "Arquitectura de CPU objetivo (ej. x86_64, aarch64)" + fr_FR: "Architecture CPU cible (ex. x86_64, aarch64)" + pl_PL: "Docelowa architektura CPU (np. x86_64, aarch64)" + help.arg.architecture-mask: en_US: "Filter by CPU architecture" de_DE: "Nach CPU-Architektur filtern" diff --git a/core/src/registry/package/get.rs b/core/src/registry/package/get.rs index 8ad7bcceb..b95095032 100644 --- a/core/src/registry/package/get.rs +++ b/core/src/registry/package/get.rs @@ -418,6 +418,9 @@ pub struct CliDownloadParams { pub target_version: Option, #[arg(short, long, help = "help.arg.destination-path")] pub dest: Option, + #[arg(long, short, help = "help.arg.architecture")] + #[ts(type = "string | null")] + pub arch: Option, } pub async fn cli_download( @@ -426,6 +429,7 @@ pub async fn cli_download( ref id, target_version, dest, + arch, }: CliDownloadParams, ) -> Result<(), Error> { let progress_tracker = FullProgressTracker::new(); @@ -473,6 +477,13 @@ pub async fn cli_download( res.best.remove(version).unwrap() } }; + if let Some(arch) = &arch { + s9pk.retain(|(hw, _)| { + hw.arch + .as_ref() + .map_or(true, |arches| arches.contains(arch)) + }); + } let s9pk = match s9pk.len() { 0 => { return Err(Error::new( From f5bfbe0465b66d26edee9653fc34309f04d4075f Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 20 Mar 2026 16:35:09 -0600 Subject: [PATCH 38/53] Revert "fix: RunAction task re-evaluation compared against partial input, not full config" also apply alternative fix: only re-activate a task that explicitly conflicts with a run action's input This reverts commit 2999d22d2a71127061968d791312a05c24d65b20. --- core/src/service/action.rs | 81 ++++++++++++++++---------------------- core/src/service/mod.rs | 27 ++++++++++--- 2 files changed, 55 insertions(+), 53 deletions(-) diff --git a/core/src/service/action.rs b/core/src/service/action.rs index 772f0dfc6..814a3c94f 100644 --- a/core/src/service/action.rs +++ b/core/src/service/action.rs @@ -9,7 +9,7 @@ use crate::db::model::package::{ }; use crate::prelude::*; use crate::rpc_continuations::Guid; -use crate::service::{ProcedureName, Service, ServiceActor, ServiceActorSeed}; +use crate::service::{ProcedureName, Service, ServiceActor}; use crate::util::actor::background::BackgroundJobQueue; use crate::util::actor::{ConflictBuilder, Handler}; use crate::util::serde::is_partial_of; @@ -83,6 +83,22 @@ impl Service { } } +fn conflicts(left: &Value, right: &Value) -> bool { + match (left, right) { + (Value::Object(left), Value::Object(right)) => left.iter().any(|(k, v)| { + if let Some(v_right) = right.get(k) { + conflicts(v, v_right) + } else { + false + } + }), + (Value::Array(left), Value::Array(right)) => left + .iter() + .any(|v| right.iter().all(|v_right| conflicts(v, v_right))), + (_, _) => left != right, + } +} + pub fn update_tasks( tasks: &mut BTreeMap, package_id: &PackageId, @@ -105,7 +121,7 @@ pub fn update_tasks( } else { v.active = false; } - } else { + } else if conflicts(value, input) { v.active = true; if v.task.severity == TaskSeverity::Critical { critical_activated = true; @@ -131,50 +147,6 @@ pub fn update_tasks( critical_activated } -impl ServiceActorSeed { - /// Fetch the current action input and re-evaluate all tasks targeting this action. - /// - /// This is the single source of truth for task re-evaluation. Used both after - /// running an action and during service init (recheck_tasks). - pub(super) async fn eval_action_tasks( - &self, - action_id: &ActionId, - was_run: bool, - ) -> Result<(), Error> { - let package_id = &self.id; - let current_input = self - .persistent_container - .execute::>( - Guid::new(), - ProcedureName::GetActionInput(action_id.clone()), - json!({ "prefill": Value::Null }), - Some(Duration::from_secs(30)), - ) - .await - .log_err() - .flatten() - .and_then(|ai| ai.value); - let Some(input) = current_input else { - return Ok(()); - }; - self.ctx - .db - .mutate(|db| { - for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { - if pde.as_tasks_mut().mutate(|tasks| { - Ok(update_tasks(tasks, package_id, action_id, &input, was_run)) - })? { - pde.as_status_info_mut().stop()?; - } - } - Ok(()) - }) - .await - .result?; - Ok(()) - } -} - pub(super) struct RunAction { action_id: ActionId, input: Value, @@ -247,7 +219,22 @@ impl Handler for ServiceActor { ) .await .with_kind(ErrorKind::Action)?; - self.0.eval_action_tasks(action_id, true).await?; + let package_id = package_id.clone(); + self.0 + .ctx + .db + .mutate(|db| { + for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { + if pde.as_tasks_mut().mutate(|tasks| { + Ok(update_tasks(tasks, &package_id, action_id, &input, true)) + })? { + pde.as_status_info_mut().stop()?; + } + } + Ok(()) + }) + .await + .result?; Ok(result) } } diff --git a/core/src/service/mod.rs b/core/src/service/mod.rs index 05c6e56ea..9fbcfa300 100644 --- a/core/src/service/mod.rs +++ b/core/src/service/mod.rs @@ -39,6 +39,7 @@ use crate::lxc::ContainerId; use crate::prelude::*; use crate::rpc_continuations::{Guid, RpcContinuation}; use crate::s9pk::S9pk; +use crate::service::action::update_tasks; use crate::service::rpc::{ExitParams, InitKind}; use crate::service::service_map::InstallProgressHandles; use crate::service::uninstall::cleanup; @@ -237,7 +238,8 @@ impl Service { async fn recheck_tasks(&self) -> Result<(), Error> { let service_id = &self.seed.id; let peek = self.seed.ctx.db.peek().await; - let action_ids: BTreeSet<_> = peek + let mut action_input: BTreeMap = BTreeMap::new(); + let tasks: BTreeSet<_> = peek .as_public() .as_package_data() .as_entries()? @@ -264,16 +266,29 @@ impl Service { .flatten_ok() .map(|a| a.and_then(|a| a)) .try_collect()?; - drop(peek); - for action_id in action_ids { - self.seed.eval_action_tasks(&action_id, false).await?; + let procedure_id = Guid::new(); + for action_id in tasks { + if let Some(input) = self + .get_action_input(procedure_id.clone(), action_id.clone(), Value::Null) + .await + .log_err() + .flatten() + .and_then(|i| i.value) + { + action_input.insert(action_id, input); + } } - // Defensive sweep: stop any package that still has an active critical task. - // This catches tasks that were already active before this init cycle. self.seed .ctx .db .mutate(|db| { + for (action_id, input) in &action_input { + for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { + pde.as_tasks_mut().mutate(|tasks| { + Ok(update_tasks(tasks, service_id, action_id, input, false)) + })?; + } + } for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? { if pde .as_tasks() From c9a93f0a3377b503fb7e30e308adb37143596c9d Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 20 Mar 2026 17:13:14 -0600 Subject: [PATCH 39/53] fix: rsync progress regex never matched, spamming logs during backup The regex used `$` (end-of-string anchor) instead of no anchor, so it never matched the percentage in rsync output. Every line, including empty ones, was logged instead of parsed. --- sdk/package/lib/backup/Backups.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/package/lib/backup/Backups.ts b/sdk/package/lib/backup/Backups.ts index 836844d4e..e137c657e 100644 --- a/sdk/package/lib/backup/Backups.ts +++ b/sdk/package/lib/backup/Backups.ts @@ -280,9 +280,9 @@ async function runRsync(rsyncOptions: { spawned.stdout.on('data', (data: unknown) => { const lines = String(data).replace(/\r/g, '\n').split('\n') for (const line of lines) { - const parsed = /$([0-9.]+)%/.exec(line)?.[1] + const parsed = /([0-9.]+)%/.exec(line)?.[1] if (!parsed) { - console.log(line) + if (line) console.log(line) continue } percentage = Number.parseFloat(parsed) From 8b65490d0e1255f486cad4dde1b1e57e7a00bcd6 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 20 Mar 2026 19:31:57 -0600 Subject: [PATCH 40/53] feat: add progress step for btrfs conversion during setup/init --- core/locales/i18n.yaml | 7 +++++++ core/src/bins/start_init.rs | 1 + core/src/disk/main.rs | 18 +++++++++++++++--- core/src/setup.rs | 12 ++++++++++-- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/core/locales/i18n.yaml b/core/locales/i18n.yaml index cce91b5e5..f1ba7dbe4 100644 --- a/core/locales/i18n.yaml +++ b/core/locales/i18n.yaml @@ -872,6 +872,13 @@ disk.main.disk-not-found: fr_FR: "Disque StartOS non trouvé." pl_PL: "Nie znaleziono dysku StartOS." +disk.main.converting-to-btrfs: + en_US: "Performing file system conversion to btrfs. This can take many hours, please be patient and DO NOT unplug the server." + de_DE: "Dateisystemkonvertierung zu btrfs wird durchgeführt. Dies kann viele Stunden dauern, bitte haben Sie Geduld und trennen Sie den Server NICHT vom Strom." + es_ES: "Realizando conversión del sistema de archivos a btrfs. Esto puede tardar muchas horas, tenga paciencia y NO desconecte el servidor." + fr_FR: "Conversion du système de fichiers vers btrfs en cours. Cela peut prendre de nombreuses heures, soyez patient et NE débranchez PAS le serveur." + pl_PL: "Wykonywanie konwersji systemu plików na btrfs. To może potrwać wiele godzin, prosimy o cierpliwość i NIE odłączaj serwera od zasilania." + disk.main.incorrect-disk: en_US: "A StartOS disk was found, but it is not the correct disk for this device." de_DE: "Eine StartOS-Festplatte wurde gefunden, aber es ist nicht die richtige Festplatte für dieses Gerät." diff --git a/core/src/bins/start_init.rs b/core/src/bins/start_init.rs index 5c53a6e0c..b47bfb075 100644 --- a/core/src/bins/start_init.rs +++ b/core/src/bins/start_init.rs @@ -159,6 +159,7 @@ async fn setup_or_init( } else { Some(DEFAULT_PASSWORD) }, + Some(&handle), ) .await?; if tokio::fs::metadata(REPAIR_DISK_PATH).await.is_ok() { diff --git a/core/src/disk/main.rs b/core/src/disk/main.rs index da0007caf..80ba3fa64 100644 --- a/core/src/disk/main.rs +++ b/core/src/disk/main.rs @@ -12,6 +12,7 @@ use super::util::pvscan; use crate::disk::mount::filesystem::block_dev::BlockDev; use crate::disk::mount::filesystem::{FileSystem, ReadWrite}; use crate::disk::mount::util::unmount; +use crate::progress::FullProgressTracker; use crate::util::Invoke; use crate::{Error, ErrorKind, ResultExt}; @@ -216,6 +217,7 @@ pub async fn import>( datadir: P, repair: RepairStrategy, password: Option<&str>, + progress: Option<&FullProgressTracker>, ) -> Result { let scan = pvscan().await?; if scan @@ -264,7 +266,7 @@ pub async fn import>( .arg(guid) .invoke(crate::ErrorKind::DiskManagement) .await?; - mount_all_fs(guid, datadir, repair, password).await + mount_all_fs(guid, datadir, repair, password, progress).await } #[instrument(skip_all)] @@ -274,6 +276,7 @@ pub async fn mount_fs>( name: &str, repair: RepairStrategy, password: Option<&str>, + progress: Option<&FullProgressTracker>, ) -> Result { let orig_path = Path::new("/dev").join(guid).join(name); let mut blockdev_path = orig_path.clone(); @@ -305,6 +308,11 @@ pub async fn mount_fs>( // Convert ext4 → btrfs on the package-data partition if needed let fs_type = detect_filesystem(&blockdev_path).await?; if fs_type == "ext2" { + let mut convert_phase = + progress.map(|p| p.add_phase(t!("disk.main.converting-to-btrfs").into(), Some(50))); + if let Some(ref mut phase) = convert_phase { + phase.start(); + } tracing::info!("Running e2fsck before converting {name} from ext4 to btrfs"); Command::new("e2fsck") .arg("-fy") @@ -330,6 +338,9 @@ pub async fn mount_fs>( .await?; unmount(&tmp_mount, false).await?; tokio::fs::remove_dir(&tmp_mount).await?; + if let Some(ref mut phase) = convert_phase { + phase.complete(); + } } let reboot = repair.fsck(&blockdev_path).await?; @@ -367,10 +378,11 @@ pub async fn mount_all_fs>( datadir: P, repair: RepairStrategy, password: Option<&str>, + progress: Option<&FullProgressTracker>, ) -> Result { let mut reboot = RequiresReboot(false); - reboot |= mount_fs(guid, &datadir, "main", repair, password).await?; - reboot |= mount_fs(guid, &datadir, "package-data", repair, password).await?; + reboot |= mount_fs(guid, &datadir, "main", repair, password, progress).await?; + reboot |= mount_fs(guid, &datadir, "package-data", repair, password, progress).await?; Ok(reboot) } diff --git a/core/src/setup.rs b/core/src/setup.rs index e6aa68212..042e91c71 100644 --- a/core/src/setup.rs +++ b/core/src/setup.rs @@ -219,6 +219,7 @@ pub async fn attach( } else { Some(DEFAULT_PASSWORD) }, + Some(&*progress), ) .await?; let _ = setup_ctx.disk_guid.set(disk_guid.clone()); @@ -396,8 +397,14 @@ pub async fn setup_data_drive( encryption_password, ) .await?; - let _ = crate::disk::main::import(&*guid, DATA_DIR, RepairStrategy::Preen, encryption_password) - .await?; + let _ = crate::disk::main::import( + &*guid, + DATA_DIR, + RepairStrategy::Preen, + encryption_password, + None, + ) + .await?; let _ = ctx.disk_guid.set(guid.clone()); Ok(guid) } @@ -726,6 +733,7 @@ async fn migrate( } else { Some(DEFAULT_PASSWORD) }, + Some(&ctx.progress), ) .await?; From bdfa918a33a79ff5e12b6beca04e9e1bd853fae7 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sat, 21 Mar 2026 16:32:46 -0600 Subject: [PATCH 41/53] a bunch of UI cleanup around backups as well as other bug fixes and UII improvements --- .../src/app/pages/success.page.ts | 16 +-- .../shared/src/i18n/dictionaries/de.ts | 12 +- .../shared/src/i18n/dictionaries/en.ts | 12 +- .../shared/src/i18n/dictionaries/es.ts | 12 +- .../shared/src/i18n/dictionaries/fr.ts | 12 +- .../shared/src/i18n/dictionaries/pl.ts | 12 +- .../src/app/routes/home/routes/devices/add.ts | 2 +- .../app/routes/home/routes/devices/config.ts | 2 +- .../app/routes/home/routes/devices/index.ts | 4 +- .../app/components/backup-report.component.ts | 83 ++++++----- .../addresses/addresses.component.ts | 27 +++- .../interfaces/addresses/plugin.component.ts | 2 +- .../interfaces/interface.service.ts | 2 + .../routes/backups/modals/backup.component.ts | 2 +- .../backups/modals/history.component.ts | 1 + .../routes/notifications/item.component.ts | 20 +-- .../authorities/authorities.component.ts | 18 ++- .../routes/backups/backups.component.ts | 130 ++++++++---------- .../routes/backups/network.component.ts | 62 +++++---- .../routes/backups/physical.component.ts | 44 +++--- .../routes/backups/progress.component.ts | 40 ++++-- .../routes/backups/restore.component.ts | 68 +++++---- .../system/routes/backups/status.component.ts | 6 +- .../routes/system/routes/dns/dns.component.ts | 22 ++- .../routes/gateways/gateways.component.ts | 22 ++- .../system/routes/smtp/smtp.component.ts | 22 ++- .../routes/system/routes/ssh/ssh.component.ts | 24 ++-- .../system/routes/wifi/wifi.component.ts | 24 +++- .../src/app/services/notification.service.ts | 54 +++++--- 29 files changed, 446 insertions(+), 311 deletions(-) diff --git a/web/projects/setup-wizard/src/app/pages/success.page.ts b/web/projects/setup-wizard/src/app/pages/success.page.ts index f21d5f4ba..8fc7884bc 100644 --- a/web/projects/setup-wizard/src/app/pages/success.page.ts +++ b/web/projects/setup-wizard/src/app/pages/success.page.ts @@ -34,15 +34,15 @@ import { StateService } from '../services/state.service' {{ 'Setup Complete!' | i18n }} + @if (!stateService.kiosk) { +

    + {{ + 'http://start.local was for setup only. It will no longer work.' + | i18n + }} +

    + } - @if (!stateService.kiosk) { -

    - {{ - 'http://start.local was for setup only. It will no longer work.' - | i18n - }} -

    - } @if (!result) { diff --git a/web/projects/shared/src/i18n/dictionaries/de.ts b/web/projects/shared/src/i18n/dictionaries/de.ts index 3215c61d6..8e93725b9 100644 --- a/web/projects/shared/src/i18n/dictionaries/de.ts +++ b/web/projects/shared/src/i18n/dictionaries/de.ts @@ -302,15 +302,11 @@ export default { 317: 'Originalpasswort', 318: 'Originalpasswort eingeben', 319: 'Sicherung wird gestartet', - 320: 'Sichern Sie StartOS und Dienstdaten, indem Sie sich mit einem Gerät im lokalen Netzwerk oder einem physischen Laufwerk verbinden, das an Ihren Server angeschlossen ist.', - 321: 'Stellen Sie StartOS und Dienstdaten von einem Gerät im lokalen Netzwerk oder einem physischen Laufwerk mit vorhandener Sicherung wieder her.', 322: 'Letzte Sicherung', - 323: 'Ein Ordner auf einem anderen Computer, der mit demselben Netzwerk wie Ihr Start9-Server verbunden ist.', - 324: 'Ein physisches Laufwerk, das direkt an Ihren Start9-Server angeschlossen ist.', - 325: 'Dienste für Sicherung auswählen', - 326: 'Serversicherung auswählen', + 325: 'Dienste auswählen', + 326: 'Server auswählen', 327: 'Netzwerkordner', - 328: 'Neuen öffnen', + 328: 'Neuen', 329: 'Hostname', 330: 'Pfad', 331: 'URL', @@ -355,7 +351,6 @@ export default { 372: 'Passwort erforderlich', 373: 'Geben Sie das Master-Passwort ein, das zur Verschlüsselung dieser Sicherung verwendet wurde. Im nächsten Schritt wählen Sie die Dienste aus, die wiederhergestellt werden sollen.', 374: 'Laufwerk wird entschlüsselt', - 375: 'Dienste zur Wiederherstellung auswählen', 376: 'Für Sicherung verfügbar', 377: 'StartOS-Sicherungen erkannt', 378: 'Keine StartOS-Sicherungen erkannt', @@ -726,4 +721,5 @@ export default { 803: 'Dieses Laufwerk verwendet ext4 und wird automatisch in btrfs konvertiert. Ein Backup wird dringend empfohlen, bevor Sie fortfahren.', 804: 'Ich habe ein Backup meiner Daten', 805: 'Öffentliche Domain hinzufügen', + 806: 'Ergebnis', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/en.ts b/web/projects/shared/src/i18n/dictionaries/en.ts index 957f839df..ed961ee84 100644 --- a/web/projects/shared/src/i18n/dictionaries/en.ts +++ b/web/projects/shared/src/i18n/dictionaries/en.ts @@ -301,15 +301,11 @@ export const ENGLISH: Record = { 'Original Password': 317, 'Enter original password': 318, 'Beginning backup': 319, - 'Back up StartOS and service data by connecting to a device on your local network or a physical drive connected to your server.': 320, - 'Restore StartOS and service data from a device on your local network or a physical drive connected to your server that contains an existing backup.': 321, 'Last Backup': 322, // as in, the last time the server was backed up - 'A folder on another computer that is connected to the same network as your Start9 server.': 323, - 'A physical drive that is plugged directly into your Start9 Server.': 324, - 'Select Services to Back Up': 325, - 'Select server backup': 326, + 'Select services': 325, + 'Select server': 326, 'Network Folders': 327, - 'Open New': 328, + 'New': 328, 'Hostname': 329, 'Path': 330, // as in, a URL path 'URL': 331, @@ -354,7 +350,6 @@ export const ENGLISH: Record = { 'Password required': 372, 'Enter the master password that was used to encrypt this backup. On the next screen, you will select the individual services you want to restore.': 373, 'Decrypting drive': 374, - 'Select services to restore': 375, 'Available for backup': 376, 'StartOS backups detected': 377, 'No StartOS backups detected': 378, @@ -727,4 +722,5 @@ export const ENGLISH: Record = { 'This drive uses ext4 and will be automatically converted to btrfs. A backup is strongly recommended before proceeding.': 803, 'I have a backup of my data': 804, 'Add Public Domain': 805, + 'Result': 806, } diff --git a/web/projects/shared/src/i18n/dictionaries/es.ts b/web/projects/shared/src/i18n/dictionaries/es.ts index 1382c1be5..01edc0200 100644 --- a/web/projects/shared/src/i18n/dictionaries/es.ts +++ b/web/projects/shared/src/i18n/dictionaries/es.ts @@ -302,15 +302,11 @@ export default { 317: 'Contraseña original', 318: 'Ingresa la contraseña original', 319: 'Iniciando copia de seguridad', - 320: 'Haz una copia de seguridad de StartOS y los datos de los servicios conectándote a un dispositivo en tu red local o a una unidad física conectada a tu servidor.', - 321: 'Restaura StartOS y los datos de los servicios desde un dispositivo en tu red local o una unidad física conectada a tu servidor que contenga una copia de seguridad existente.', 322: 'Última copia de seguridad', - 323: 'Una carpeta en otro ordenador conectado a la misma red que tu servidor Start9.', - 324: 'Una unidad física conectada directamente a tu servidor Start9.', - 325: 'Seleccionar servicios para respaldar', - 326: 'Seleccionar copia de seguridad del servidor', + 325: 'Seleccionar servicios', + 326: 'Seleccionar servidor', 327: 'Carpetas de red', - 328: 'Abrir nuevo', + 328: 'Nuevo', 329: 'Nombre del host', 330: 'Ruta', 331: 'URL', @@ -355,7 +351,6 @@ export default { 372: 'Se requiere contraseña', 373: 'Ingresa la contraseña maestra que se usó para cifrar esta copia de seguridad. En la siguiente pantalla, podrás seleccionar los servicios individuales que deseas restaurar.', 374: 'Descifrando unidad', - 375: 'Seleccionar servicios para restaurar', 376: 'Disponible para copia de seguridad', 377: 'Copias de seguridad de StartOS detectadas', 378: 'No se detectaron copias de seguridad de StartOS', @@ -726,4 +721,5 @@ export default { 803: 'Esta unidad usa ext4 y se convertirá automáticamente a btrfs. Se recomienda encarecidamente hacer una copia de seguridad antes de continuar.', 804: 'Tengo una copia de seguridad de mis datos', 805: 'Agregar dominio público', + 806: 'Resultado', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/fr.ts b/web/projects/shared/src/i18n/dictionaries/fr.ts index 7fac66a9d..aa9460f85 100644 --- a/web/projects/shared/src/i18n/dictionaries/fr.ts +++ b/web/projects/shared/src/i18n/dictionaries/fr.ts @@ -302,15 +302,11 @@ export default { 317: 'Mot de passe d’origine', 318: 'Entrez le mot de passe d’origine', 319: 'Démarrage de la sauvegarde', - 320: 'Sauvegardez StartOS et les données des services en connectant un appareil sur votre réseau local ou un disque physique connecté à votre serveur.', - 321: 'Restaurez StartOS et les données des services à partir d’un appareil sur votre réseau local ou d’un disque physique connecté à votre serveur contenant une sauvegarde.', 322: 'Dernière sauvegarde', - 323: 'Un dossier sur un autre ordinateur connecté au même réseau que votre serveur Start9.', - 324: 'Un disque physique branché directement à votre serveur Start9.', - 325: 'Sélectionner les services à sauvegarder', - 326: 'Sélectionner la sauvegarde du serveur', + 325: 'Sélectionner les services', + 326: 'Sélectionner le serveur', 327: 'Dossiers réseau', - 328: 'Ouvrir nouveau', + 328: 'Nouveau', 329: 'Nom d’hôte', 330: 'Chemin', 331: 'URL', @@ -355,7 +351,6 @@ export default { 372: 'Mot de passe requis', 373: 'Entrez le mot de passe principal utilisé pour chiffrer cette sauvegarde. Vous pourrez choisir les services à restaurer à l’écran suivant.', 374: 'Déchiffrement du disque', - 375: 'Sélectionner les services à restaurer', 376: 'Disponible pour la sauvegarde', 377: 'Sauvegardes StartOS détectées', 378: 'Aucune sauvegarde StartOS détectée', @@ -726,4 +721,5 @@ export default { 803: 'Ce disque utilise ext4 et sera automatiquement converti en btrfs. Il est fortement recommandé de faire une sauvegarde avant de continuer.', 804: "J'ai une sauvegarde de mes données", 805: 'Ajouter un domaine public', + 806: 'Résultat', } satisfies i18n diff --git a/web/projects/shared/src/i18n/dictionaries/pl.ts b/web/projects/shared/src/i18n/dictionaries/pl.ts index 2c412f701..d8ffd4153 100644 --- a/web/projects/shared/src/i18n/dictionaries/pl.ts +++ b/web/projects/shared/src/i18n/dictionaries/pl.ts @@ -302,15 +302,11 @@ export default { 317: 'Oryginalne hasło', 318: 'Wprowadź oryginalne hasło', 319: 'Rozpoczynanie tworzenia kopii zapasowej', - 320: 'Utwórz kopię zapasową StartOS i danych serwisów, łącząc się z urządzeniem w sieci lokalnej lub z fizycznym dyskiem podłączonym do Twojego serwera.', - 321: 'Przywróć StartOS i dane serwisów z urządzenia w sieci lokalnej lub z fizycznego dysku podłączonego do Twojego serwera, który zawiera istniejącą kopię zapasową.', 322: 'Ostatnia kopia zapasowa', - 323: 'Folder na innym komputerze, który jest podłączony do tej samej sieci co twój serwer Start9.', - 324: 'Fizyczny dysk, który jest podłączony bezpośrednio do Twojego serwera Start9.', - 325: 'Wybierz serwisy do kopii zapasowej', - 326: 'Wybierz kopię zapasową serwera', + 325: 'Wybierz serwisy', + 326: 'Wybierz serwer', 327: 'Foldery sieciowe', - 328: 'Otwórz nowy', + 328: 'Nowy', 329: 'Nazwa hosta', 330: 'Ścieżka', 331: 'URL', @@ -355,7 +351,6 @@ export default { 372: 'Wymagane hasło', 373: 'Wprowadź hasło główne, które zostało użyte do zaszyfrowania tej kopii zapasowej. Na następnym ekranie wybierzesz poszczególne serwisy, które chcesz przywrócić.', 374: 'Odszyfrowywanie dysku', - 375: 'Wybierz serwisy do przywrócenia', 376: 'Dostępne do kopii zapasowej', 377: 'Wykryto kopie zapasowe StartOS', 378: 'Nie wykryto kopii zapasowych StartOS', @@ -726,4 +721,5 @@ export default { 803: 'Ten dysk używa ext4 i zostanie automatycznie skonwertowany na btrfs. Zdecydowanie zaleca się wykonanie kopii zapasowej przed kontynuowaniem.', 804: 'Mam kopię zapasową moich danych', 805: 'Dodaj domenę publiczną', + 806: 'Wynik', } satisfies i18n diff --git a/web/projects/start-tunnel/src/app/routes/home/routes/devices/add.ts b/web/projects/start-tunnel/src/app/routes/home/routes/devices/add.ts index 790ea6f9c..fe10d0b82 100644 --- a/web/projects/start-tunnel/src/app/routes/home/routes/devices/add.ts +++ b/web/projects/start-tunnel/src/app/routes/home/routes/devices/add.ts @@ -169,7 +169,7 @@ export class DevicesAdd { }) this.dialogs - .open(DEVICES_CONFIG, { data: config, closable: false }) + .open(DEVICES_CONFIG, { data: config, closable: false, size: 'm' }) .subscribe() } } catch (e: any) { diff --git a/web/projects/start-tunnel/src/app/routes/home/routes/devices/config.ts b/web/projects/start-tunnel/src/app/routes/home/routes/devices/config.ts index 3e6587875..4f495039e 100644 --- a/web/projects/start-tunnel/src/app/routes/home/routes/devices/config.ts +++ b/web/projects/start-tunnel/src/app/routes/home/routes/devices/config.ts @@ -22,7 +22,7 @@ import { QrCodeComponent } from 'ng-qrcode' - @if (segmented?.activeItemIndex) { + @if (segmented?.activeItemIndex()) { } @else { diff --git a/web/projects/start-tunnel/src/app/routes/home/routes/devices/index.ts b/web/projects/start-tunnel/src/app/routes/home/routes/devices/index.ts index 6867d00f7..89dca6941 100644 --- a/web/projects/start-tunnel/src/app/routes/home/routes/devices/index.ts +++ b/web/projects/start-tunnel/src/app/routes/home/routes/devices/index.ts @@ -159,7 +159,9 @@ export default class Devices { try { const data = await this.api.showDeviceConfig({ subnet: subnet.range, ip }) - this.dialogs.open(DEVICES_CONFIG, { data, closable: false }).subscribe() + this.dialogs + .open(DEVICES_CONFIG, { data, closable: false, size: 'm' }) + .subscribe() } catch (e: any) { console.log(e) this.errorService.handleError(e) diff --git a/web/projects/ui/src/app/components/backup-report.component.ts b/web/projects/ui/src/app/components/backup-report.component.ts index 628c08b0a..d2a70f36f 100644 --- a/web/projects/ui/src/app/components/backup-report.component.ts +++ b/web/projects/ui/src/app/components/backup-report.component.ts @@ -7,7 +7,7 @@ import { } from '@angular/core' import { toSignal } from '@angular/core/rxjs-interop' import { i18nKey, i18nPipe } from '@start9labs/shared' -import { TuiDialogContext, TuiIcon, TuiTitle, TuiCell } from '@taiga-ui/core' +import { TuiDialogContext, TuiIcon } from '@taiga-ui/core' import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus' import { PatchDB } from 'patch-db-client' import { map } from 'rxjs' @@ -17,41 +17,58 @@ import { DataModel } from '../services/patch-db/data-model' @Component({ template: ` -

    - {{ 'Completed' | i18n }}: {{ data.createdAt | date: 'medium' }} -

    -
    -
    - {{ 'System data' | i18n }} -
    - {{ system().result | i18n }} -
    -
    - -
    - @if (pkgTitles(); as titles) { - @for (pkg of data.content.packages | keyvalue; track $index) { -
    -
    - {{ titles[pkg.key] || pkg.key }} -
    - {{ - pkg.value.error - ? ('Failed' | i18n) + ': ' + pkg.value.error - : ('Succeeded' | i18n) - }} -
    -
    - -
    - } +

    {{ data.createdAt | date: 'medium' }}

    + + + + + + + + + + + + + @if (pkgTitles(); as titles) { + @for (pkg of data.content.packages | keyvalue; track $index) { + + + + + } + } + +
    {{ 'Title' | i18n }}{{ 'Result' | i18n }}
    {{ 'System data' | i18n }} + + {{ system().result | i18n }} +
    {{ titles[pkg.key] || pkg.key }} + + {{ + pkg.value.error + ? ('Failed' | i18n) + ': ' + pkg.value.error + : ('Succeeded' | i18n) + }} +
    + `, + styles: ` + .timestamp { + color: var(--tui-text-secondary); + margin: 0 0 1rem; + } + + td:first-child { + white-space: nowrap; + } + + tui-icon { + font-size: 1rem; + vertical-align: sub; + margin-inline-end: 0.25rem; } `, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule, TuiIcon, TuiCell, TuiTitle, i18nPipe], + imports: [CommonModule, TuiIcon, i18nPipe], }) export class BackupsReportModal { private readonly i18n = inject(i18nPipe) diff --git a/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts b/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts index 3a8688556..0cc9e7708 100644 --- a/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts +++ b/web/projects/ui/src/app/routes/portal/components/interfaces/addresses/addresses.component.ts @@ -7,7 +7,13 @@ import { } from '@angular/core' import { ErrorService, i18nPipe } from '@start9labs/shared' import { ISB, utils } from '@start9labs/start-sdk' -import { TuiButton, TuiDataList, TuiDropdown, TuiInput } from '@taiga-ui/core' +import { + TuiButton, + TuiDataList, + TuiDropdown, + TuiIcon, + TuiInput, +} from '@taiga-ui/core' import { TuiNotificationMiddleService } from '@taiga-ui/kit' import { PatchDB } from 'patch-db-client' import { firstValueFrom } from 'rxjs' @@ -33,7 +39,18 @@ import { InterfaceAddressItemComponent } from './item.component' selector: 'section[gatewayGroup]', template: `
    - {{ 'Gateway' | i18n }}: {{ gatewayGroup().gatewayName }} + @switch (gatewayGroup().deviceType) { + @case ('ethernet') { + + } + @case ('wireless') { + + } + @case ('wireguard') { + + } + } + {{ gatewayGroup().gatewayName }} @if (gatewayGroup().isWireguard) {
- @if (overflow) { - - } @if ([1, 2].includes(item.code)) { + } @else if (overflow) { + } {{ target.entry.path.split('/').pop() }} {{ target.entry.hostname }} {{ target.entry.path }} + - + +
+
@for (target of service.drives(); track $index) { - - - + + + } @empty { @@ -74,10 +66,6 @@ import { BackupStatusComponent } from './status.component' } } - td:first-child { - width: 13rem; - } - :host-context(tui-root._mobile) { tr { grid-template-columns: min-content 1fr 4rem; @@ -109,9 +97,6 @@ import { BackupStatusComponent } from './status.component' changeDetection: ChangeDetectionStrategy.OnPush, imports: [ TuiButton, - TuiIcon, - TuiTooltip, - ConvertBytesPipe, PlaceholderComponent, BackupStatusComponent, TableComponent, @@ -122,9 +107,26 @@ export class BackupPhysicalComponent { private readonly dialog = inject(DialogService) private readonly type = inject(ActivatedRoute).snapshot.data['type'] + private readonly i18n = inject(i18nPipe) + readonly service = inject(BackupService) readonly physicalFolders = output>() + driveName(entry: DiskBackupTarget): string { + return ( + [entry.vendor, entry.model].filter(Boolean).join(' ') || + this.i18n.transform('Unknown Drive') + ) + } + + formatCapacity(bytes: number): string { + const gb = bytes / 1e9 + if (gb >= 1000) { + return `${(gb / 1000).toFixed(1)} TB` + } + return `${gb.toFixed(0)} GB` + } + select(target: MappedBackupTarget) { if (this.type === 'restore' && !target.hasAnyBackup) { this.dialog diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/progress.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/progress.component.ts index 7a597e7f6..365db87e9 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/progress.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/progress.component.ts @@ -22,24 +22,42 @@ import { DataModel } from 'src/app/services/patch-db/data-model' {{ (pkg.value | toManifest).title }} - - @if (progress.complete) { - - {{ 'complete' | i18n }} + + + @if (progress.complete) { + + {{ 'complete' | i18n }} + } @else { + @if ((pkg.key | tuiMapper: toStatus | async) === 'backing-up') { + + {{ 'backing up' | i18n }} } @else { - @if ((pkg.key | tuiMapper: toStatus | async) === 'backing-up') { - - {{ 'backing up' | i18n }} - } @else { - {{ 'waiting' | i18n }} - } + + {{ 'waiting' | i18n }} } - + } } } `, + styles: ` + :host { + max-width: 36rem; + } + + .status { + display: flex; + align-items: center; + gap: 0.25rem; + margin-inline-start: auto; + white-space: nowrap; + } + + .status tui-icon { + font-size: 1rem; + } + `, host: { class: 'g-card' }, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/restore.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/restore.component.ts index d84099b1c..7cc9f2d58 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/restore.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/restore.component.ts @@ -3,12 +3,12 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { DialogService, ErrorService, - i18nPipe, StartOSDiskInfo, } from '@start9labs/shared' -import { TuiCell, TuiTitle } from '@taiga-ui/core' +import { TuiButton } from '@taiga-ui/core' import { TuiNotificationMiddleService } from '@taiga-ui/kit' import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus' +import { TableComponent } from 'src/app/routes/portal/components/table.component' import { ApiService } from 'src/app/services/api/embassy-api.service' import { verifyPassword } from 'src/app/utils/verify-password' import { BackupContext } from './backup.types' @@ -16,31 +16,49 @@ import { RECOVER } from './recover.component' @Component({ template: ` - @for (server of target.entry.startOs | keyvalue; track $index) { - +
- {{ target.entry.label || target.entry.logicalname }} - - {{ target.entry.vendor || 'Unknown Vendor' }} - - {{ target.entry.model || 'Unknown Model' }} - {{ target.entry.capacity | convertBytes }}{{ target.entry.logicalname }}{{ driveName(target.entry) }}{{ formatCapacity(target.entry.capacity) }}
+ @for (server of target.entry.startOs | keyvalue; track $index) { + + + + + + + } +
{{ server.value.hostname }}.local{{ server.value.version }}{{ server.value.timestamp | date: 'medium' }} + +
+ `, + styles: ` + td:last-child { + text-align: right; + } + + :host-context(tui-root._mobile) { + tr { + grid-template-columns: 1fr auto; + } + + .name { + color: var(--tui-text-primary); + font: var(--tui-typography-body-m); + font-weight: bold; + } + + td:last-child { + grid-area: 1 / 2 / 4 / 2; + align-self: center; + } } `, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [KeyValuePipe, DatePipe, TuiCell, TuiTitle, i18nPipe], + imports: [KeyValuePipe, DatePipe, TuiButton, TableComponent], }) export class BackupRestoreComponent { private readonly dialog = inject(DialogService) @@ -82,7 +100,7 @@ export class BackupRestoreComponent { this.context.$implicit.complete() this.dialog - .openComponent(RECOVER, { label: 'Select services to restore', data }) + .openComponent(RECOVER, { label: 'Select services', data }) .subscribe() } finally { loader.unsubscribe() diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/status.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/status.component.ts index 20e26faf8..de84f1885 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/status.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/backups/status.component.ts @@ -13,7 +13,7 @@ import { TuiIcon } from '@taiga-ui/core' template: ` @if (type === 'create') { {{ 'Available for backup' | i18n }} @@ -22,7 +22,7 @@ import { TuiIcon } from '@taiga-ui/core' {{ 'StartOS backups detected' | i18n }} } @else { - + {{ 'No StartOS backups detected' | i18n }} } } @@ -37,6 +37,8 @@ import { TuiIcon } from '@taiga-ui/core' tui-icon { font-size: 1rem; + min-width: 1.25rem; + text-align: center; } :host-context(tui-root._mobile) { diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts index f70b13348..679b8d063 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts @@ -27,10 +27,20 @@ const ipv6 = @Component({ template: ` - - {{ 'Back' | i18n }} - - {{ 'DNS Servers' | i18n }} +
+ + {{ 'Back' | i18n }} + + {{ 'DNS Servers' | i18n }} + +
@if (data(); as d) {
@@ -76,6 +86,10 @@ const ipv6 = max-width: 36rem; } + :host-context(tui-root._mobile) [tuiHeader] { + display: none; + } + form header, form footer { margin: 1rem 0; diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/gateways/gateways.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/gateways/gateways.component.ts index 0b9776e2e..08666d2cc 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/gateways/gateways.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/gateways/gateways.component.ts @@ -29,10 +29,20 @@ import { GatewaysTableComponent } from './table.component' @Component({ template: ` - - {{ 'Back' | i18n }} - - {{ 'Gateways' | i18n }} +
+ + {{ 'Back' | i18n }} + + {{ 'Gateways' | i18n }} + +
@@ -121,6 +131,10 @@ import { GatewaysTableComponent } from './table.component' } `, styles: ` + :host-context(tui-root._mobile) .g-card > header > [docsLink] { + display: none; + } + .outbound { max-width: 24rem; margin-top: 2rem; diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/smtp/smtp.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/smtp/smtp.component.ts index 6ee478ba5..aa4dabe01 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/smtp/smtp.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/smtp/smtp.component.ts @@ -40,10 +40,20 @@ function detectProviderKey(host: string | undefined): string { @Component({ template: ` - - {{ 'Back' | i18n }} - - SMTP + @if (form$ | async; as data) { @@ -129,6 +139,10 @@ function detectProviderKey(host: string | undefined): string { max-width: 36rem; } + :host-context(tui-root._mobile) form:first-of-type > [tuiHeader] { + display: none; + } + form header, form footer { margin: 1rem 0; diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/ssh/ssh.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/ssh/ssh.component.ts index e25e9f86f..9612690a1 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/ssh/ssh.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/ssh/ssh.component.ts @@ -26,15 +26,11 @@ import { SSHTableComponent } from './table.component' @Component({ template: ` - - {{ 'Back' | i18n }} - - SSH - - @let keys = keys$ | async; -
-
- {{ 'SSH Keys' | i18n }} + + + @let keys = keys$ | async; +
+
+ {{ 'SSH Keys' | i18n }}

@@ -131,6 +141,10 @@ import { wifiSpec } from './wifi.const' :host { max-width: 36rem; } + + :host-context(tui-root._mobile) header > [docsLink] { + display: none; + } `, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ diff --git a/web/projects/ui/src/app/services/notification.service.ts b/web/projects/ui/src/app/services/notification.service.ts index e6721e9b3..5dedae10f 100644 --- a/web/projects/ui/src/app/services/notification.service.ts +++ b/web/projects/ui/src/app/services/notification.service.ts @@ -36,7 +36,7 @@ export class NotificationService { getColor(notification: ServerNotification): string { switch (notification.level) { case 'info': - return 'var(--tui-status-info)' + return 'var(--tui-text-secondary)' case 'success': return 'var(--tui-status-positive)' case 'warning': @@ -62,26 +62,42 @@ export class NotificationService { } } - viewModal(notification: ServerNotification, full = false) { + viewModal(notification: ServerNotification) { const { data, createdAt, code, title, message } = notification - if (code === 1) { - // Backup Report - this.dialogs - .openComponent(full ? message : REPORT, { - label: 'Backup Report', - data: { content: data, createdAt }, - }) - .subscribe() - } else { - // Markdown viewer - this.dialogs - .openComponent(full ? message : MARKDOWN, { - label: title as i18nKey, - data: of(data), - size: 'l', - }) - .subscribe() + switch (code) { + // Backup report - structured report with per-service results + case 1: + this.dialogs + .openComponent(REPORT, { + label: 'Backup Report', + data: { content: data, createdAt }, + size: 'l', + }) + .subscribe() + break + + // OS update - data contains the full release notes markdown + case 2: + this.dialogs + .openComponent(MARKDOWN, { + label: title as i18nKey, + data: of(data), + size: 'l', + }) + .subscribe() + break + + // General notification - show the message text + default: + this.dialogs + .openComponent(MARKDOWN, { + label: title as i18nKey, + data: of(message), + size: 'l', + }) + .subscribe() + break } } } From 456c5d672538c1d31677a2fc7a0487bbe3177be6 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Sat, 21 Mar 2026 18:19:41 -0600 Subject: [PATCH 42/53] fix: graceful shutdown for subcontainer daemons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues fixed: 1. Process group cascade: exec-command processes inherited the container runtime's process group. When an entrypoint script did kill(0, SIGTERM) during shutdown, it signaled ALL processes in the group — including other subcontainers' launch wrappers, causing their PID namespaces to collapse. Fixed by calling setsid() in exec-command's pre_exec to isolate each service in its own process group. 2. Unordered daemon termination: removeChild("main") fired onLeaveContext callbacks for all Daemon.of() instances simultaneously, bypassing Daemons.term()'s reverse-dependency ordering. Fixed by having Daemons.build() mark individual daemons as managed (suppressing their onLeaveContext) and registering a single onLeaveContext that calls the ordered Daemons.term(). The term() method is deduplicated so system.stop() and onLeaveContext share the same shutdown. --- core/src/service/effects/subcontainer/sync.rs | 4 ++++ sdk/package/lib/mainFn/Daemon.ts | 16 ++++++++++++++-- sdk/package/lib/mainFn/Daemons.ts | 12 ++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/core/src/service/effects/subcontainer/sync.rs b/core/src/service/effects/subcontainer/sync.rs index e37207ced..c4d27994a 100644 --- a/core/src/service/effects/subcontainer/sync.rs +++ b/core/src/service/effects/subcontainer/sync.rs @@ -283,6 +283,10 @@ impl ExecParams { let set_gid = gid.ok(); unsafe { cmd.pre_exec(move || { + // Create a new process group so entrypoint scripts that do + // kill(0, SIGTERM) don't cascade to other subcontainers. + nix::unistd::setsid() + .map_err(|e| std::io::Error::from_raw_os_error(e as i32))?; if !groups.is_empty() { nix::unistd::setgroups(&groups) .map_err(|e| std::io::Error::from_raw_os_error(e as i32))?; diff --git a/sdk/package/lib/mainFn/Daemon.ts b/sdk/package/lib/mainFn/Daemon.ts index 242c5827d..8b464dac8 100644 --- a/sdk/package/lib/mainFn/Daemon.ts +++ b/sdk/package/lib/mainFn/Daemon.ts @@ -27,6 +27,7 @@ export class Daemon< protected exitedSuccess = false private onExitFns: ((success: boolean) => void)[] = [] private loop: { abort: AbortController; done: Promise } | null = null + private _managed = false protected constructor( private subcontainer: C, private startCommand: () => Promise>, @@ -42,7 +43,8 @@ export class Daemon< * Factory method to create a new Daemon. * * Returns a curried function: `(effects, subcontainer, exec) => Daemon`. - * The daemon auto-terminates when the effects context is left. + * Registers an `onLeaveContext` callback that terminates the daemon when the + * effects context is left. */ static of() { return | null>( @@ -60,7 +62,9 @@ export class Daemon< ) const res = new Daemon(subc, startCommand) effects.onLeaveContext(() => { - res.term({ destroySubcontainer: true }).catch((e) => logErrorOnce(e)) + if (!res._managed) { + res.term({ destroySubcontainer: true }).catch((e) => logErrorOnce(e)) + } }) return res } @@ -173,6 +177,14 @@ export class Daemon< await this.subcontainer?.destroy() } } + /** + * Mark this daemon as managed by a {@link Daemons} instance. + * Suppresses the individual `onLeaveContext` termination since the + * `Daemons` instance handles ordered shutdown. + */ + markManaged() { + this._managed = true + } /** Get a reference-counted handle to the daemon's subcontainer, or null if there is none */ subcontainerRc(): SubContainerRc | null { return this.subcontainer?.rc() ?? null diff --git a/sdk/package/lib/mainFn/Daemons.ts b/sdk/package/lib/mainFn/Daemons.ts index 4b6bc69c0..69bd078e9 100644 --- a/sdk/package/lib/mainFn/Daemons.ts +++ b/sdk/package/lib/mainFn/Daemons.ts @@ -176,6 +176,7 @@ Daemons.of({ export class Daemons implements T.DaemonBuildable { + private termPromise: Promise | null = null private constructor( readonly effects: T.Effects, readonly ids: Ids[], @@ -413,6 +414,13 @@ export class Daemons * if a dependency cycle is detected. */ async term() { + if (!this.termPromise) { + this.termPromise = this._term() + } + return this.termPromise + } + + private async _term() { const remaining = new Set(this.healthDaemons) while (remaining.size > 0) { @@ -459,7 +467,11 @@ export class Daemons * @returns This `Daemons` instance, now running */ async build() { + this.effects.onLeaveContext(() => { + this.term().catch((e) => console.error(e)) + }) for (const daemon of this.healthDaemons) { + daemon.daemon?.markManaged() await daemon.updateStatus() } return this From cb7618cb34a638c5778b8b2f579ca6d5a71d1fe3 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Sat, 21 Mar 2026 18:20:15 -0600 Subject: [PATCH 43/53] fix: e2fsck exit codes 1-3 are non-fatal during btrfs conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit e2fsck returns 1 when errors are corrected and 2 when corrections require a reboot. These are expected during ext4→btrfs conversion. Only exit codes >= 4 indicate actual failure. Previously, .invoke() treated any non-zero exit as an error, causing the conversion to fail after successful filesystem repairs. --- core/src/disk/main.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/core/src/disk/main.rs b/core/src/disk/main.rs index 80ba3fa64..a88c94ab1 100644 --- a/core/src/disk/main.rs +++ b/core/src/disk/main.rs @@ -314,11 +314,30 @@ pub async fn mount_fs>( phase.start(); } tracing::info!("Running e2fsck before converting {name} from ext4 to btrfs"); - Command::new("e2fsck") + // e2fsck exit codes: 0 = no errors, 1 = errors corrected, 2 = corrected + reboot needed + // Only codes >= 4 indicate actual failure, so we can't use .invoke() which treats any + // non-zero exit as an error. + let e2fsck_output = Command::new("e2fsck") .arg("-fy") .arg(&blockdev_path) - .invoke(ErrorKind::DiskManagement) - .await?; + .kill_on_drop(true) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .output() + .await + .with_kind(ErrorKind::DiskManagement)?; + let e2fsck_exit = e2fsck_output.status.code().unwrap_or(4); + if e2fsck_exit >= 4 { + let msg = std::str::from_utf8( + if e2fsck_output.stderr.is_empty() { + &e2fsck_output.stdout + } else { + &e2fsck_output.stderr + }, + ) + .unwrap_or("e2fsck failed"); + return Err(Error::new(eyre!("{msg}"), ErrorKind::DiskManagement)); + } tracing::info!("Converting {name} from ext4 to btrfs"); Command::new("btrfs-convert") .arg("--no-progress") From 6ed0afc75f78e00ba1ba29ee629729c646339c40 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Sun, 22 Mar 2026 14:13:28 -0600 Subject: [PATCH 44/53] chore: bump sdk to 0.4.0-beta.63 --- sdk/CHANGELOG.md | 12 ++++++++++++ sdk/Makefile | 2 +- sdk/package/package-lock.json | 4 ++-- sdk/package/package.json | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 9adcecc15..3285ef34f 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 0.4.0-beta.63 — StartOS v0.4.0-alpha.22 (2026-03-22) + +### Fixed + +- Fixed `createTask` failing when input values are undefined +- Fixed daemon lifecycle cleanup and error logging improvements +- Replaced fire-and-forget restart loop in `Daemon` with tracked `AbortController` +- Fixed graceful shutdown for subcontainer daemons +- Fixed rsync progress regex never matching, spamming logs during backup +- Fixed rsync backup bugs and optimized flags for encrypted CIFS targets +- Fixed types in `inputSpecConstants`, `StartSdk`, and exports + ## 0.4.0-beta.62 (2026-03-19) ### Fixed diff --git a/sdk/Makefile b/sdk/Makefile index c793b3594..fda32a5c5 100644 --- a/sdk/Makefile +++ b/sdk/Makefile @@ -73,7 +73,7 @@ base/node_modules: base/package-lock.json node_modules: package/node_modules base/node_modules publish: bundle package/package.json README.md LICENSE CHANGELOG.md - cd dist && npm publish --access=public --tag=latest + cd dist && npm publish --access=public --tag=latest $(if $(OTP),--otp=$(OTP)) link: bundle cd dist && npm link diff --git a/sdk/package/package-lock.json b/sdk/package/package-lock.json index 9ce9ef680..fa173dd37 100644 --- a/sdk/package/package-lock.json +++ b/sdk/package/package-lock.json @@ -1,12 +1,12 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.62", + "version": "0.4.0-beta.63", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.62", + "version": "0.4.0-beta.63", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", diff --git a/sdk/package/package.json b/sdk/package/package.json index 182235178..0870f5259 100644 --- a/sdk/package/package.json +++ b/sdk/package/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.62", + "version": "0.4.0-beta.63", "description": "Software development kit to facilitate packaging services for StartOS", "main": "./package/lib/index.js", "types": "./package/lib/index.d.ts", From 7ffb462355cbeb81fddab65a55f057c04b48e052 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sun, 22 Mar 2026 19:49:58 -0600 Subject: [PATCH 45/53] better smtp and backups for postgres and mysql --- sdk/CHANGELOG.md | 8 + .../lib/actions/input/inputSpecConstants.ts | 13 + sdk/package/lib/StartSdk.ts | 12 + sdk/package/lib/backup/Backups.ts | 396 ++++++++++++++++++ sdk/package/lib/index.ts | 1 + sdk/package/package-lock.json | 4 +- sdk/package/package.json | 2 +- 7 files changed, 433 insertions(+), 3 deletions(-) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 3285ef34f..ef30ea57c 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.4.0-beta.64 (2026-03-22) + +### Added + +- `Backups.withPgDump()`: dump-based PostgreSQL backup using `pg_dump`/`pg_restore`, replacing raw volume rsync of PG data directories +- `Backups.withMysqlDump()`: dump-based MySQL/MariaDB backup using `mysqldump`/`mysql` +- Password configs accept `string | (() => string | Promise)` for deferred resolution during restore + ## 0.4.0-beta.63 — StartOS v0.4.0-alpha.22 (2026-03-22) ### Fixed diff --git a/sdk/base/lib/actions/input/inputSpecConstants.ts b/sdk/base/lib/actions/input/inputSpecConstants.ts index 8fe4eb098..633d8e338 100644 --- a/sdk/base/lib/actions/input/inputSpecConstants.ts +++ b/sdk/base/lib/actions/input/inputSpecConstants.ts @@ -267,3 +267,16 @@ export const smtpShape: z.ZodType = z }), ]) .catch({ selection: 'disabled' as const, value: {} }) as any + +/** + * Convert a stored SmtpSelection to a value suitable for prefilling smtpInputSpec. + * + * The stored type (SmtpSelection from smtpShape) uses flat unions for provider/security + * selection, while the input spec (smtpInputSpec) uses distributed discriminated unions + * (UnionRes). These are structurally incompatible in TypeScript's type system, even + * though the runtime values are identical. This function bridges the two types so that + * service code doesn't need `as any`. + */ +export function smtpPrefill(smtp: SmtpSelection | null | undefined): any { + return smtp || undefined +} diff --git a/sdk/package/lib/StartSdk.ts b/sdk/package/lib/StartSdk.ts index 9df7164fa..f70e775bf 100644 --- a/sdk/package/lib/StartSdk.ts +++ b/sdk/package/lib/StartSdk.ts @@ -712,6 +712,18 @@ export class StartSdk { * @param options - Partial sync options to override defaults */ withOptions: Backups.withOptions, + /** + * Create a Backups configuration that uses pg_dump/pg_restore instead of + * rsyncing the raw PostgreSQL data directory. Chain `.addVolume()` to include + * additional volumes in the backup. + */ + withPgDump: Backups.withPgDump, + /** + * Create a Backups configuration that uses mysqldump/mysql instead of + * rsyncing the raw MySQL/MariaDB data directory. Chain `.addVolume()` to + * include additional volumes in the backup. + */ + withMysqlDump: Backups.withMysqlDump, }, InputSpec: { /** diff --git a/sdk/package/lib/backup/Backups.ts b/sdk/package/lib/backup/Backups.ts index e137c657e..335c8482f 100644 --- a/sdk/package/lib/backup/Backups.ts +++ b/sdk/package/lib/backup/Backups.ts @@ -3,6 +3,63 @@ import * as child_process from 'child_process' import * as fs from 'fs/promises' import { Affine, asError } from '../util' import { InitKind, InitScript } from '../../../base/lib/inits' +import { SubContainerRc, execFile } from '../util/SubContainer' +import { Mounts } from '../mainFn/Mounts' + +const BACKUP_HOST_PATH = '/media/startos/backup' +const BACKUP_CONTAINER_MOUNT = '/backup-target' + +/** A password value, or a function that returns one. Functions are resolved lazily (only during restore). */ +export type LazyPassword = string | (() => string | Promise) + +async function resolvePassword(pw: LazyPassword): Promise { + return typeof pw === 'function' ? pw() : pw +} + +/** Configuration for PostgreSQL dump-based backup */ +export type PgDumpConfig = { + /** Image ID of the PostgreSQL container (e.g. 'postgres') */ + imageId: keyof M['images'] & T.ImageId + /** Volume ID containing the PostgreSQL data directory */ + dbVolume: M['volumes'][number] + /** Path to PGDATA within the container (e.g. '/var/lib/postgresql/data') */ + pgdata: string + /** PostgreSQL database name to dump */ + database: string + /** PostgreSQL user */ + user: string + /** PostgreSQL password (for restore). Can be a string or a function that returns one — functions are resolved lazily after volumes are restored. */ + password: LazyPassword + /** Additional initdb arguments (e.g. ['--data-checksums']) */ + initdbArgs?: string[] +} + +/** Configuration for MySQL/MariaDB dump-based backup */ +export type MysqlDumpConfig = { + /** Image ID of the MySQL/MariaDB container (e.g. 'mysql', 'mariadb') */ + imageId: keyof M['images'] & T.ImageId + /** Volume ID containing the MySQL data directory */ + dbVolume: M['volumes'][number] + /** Path to MySQL data directory within the container (typically '/var/lib/mysql') */ + datadir: string + /** MySQL database name to dump */ + database: string + /** MySQL user for dump operations */ + user: string + /** MySQL password. Can be a string or a function that returns one — functions are resolved lazily after volumes are restored. */ + password: LazyPassword + /** Database engine: 'mysql' uses --initialize-insecure, 'mariadb' uses mysql_install_db */ + engine: 'mysql' | 'mariadb' + /** Custom readiness check command (default: ['mysqladmin', 'ping', ...]) */ + readyCommand?: string[] +} + +/** Bind-mount the backup target into a SubContainer's rootfs */ +async function mountBackupTarget(rootfs: string) { + const target = `${rootfs}${BACKUP_CONTAINER_MOUNT}` + await fs.mkdir(target, { recursive: true }) + await execFile('mount', ['--rbind', BACKUP_HOST_PATH, target]) +} /** Default rsync options used for backup and restore operations */ export const DEFAULT_OPTIONS: T.SyncOptions = { @@ -79,6 +136,345 @@ export class Backups implements InitScript { return new Backups({ ...DEFAULT_OPTIONS, ...options }) } + /** + * Configure PostgreSQL dump-based backup for a volume. + * + * Instead of rsyncing the raw PostgreSQL data directory (which is slow and error-prone), + * this uses `pg_dump` to create a logical dump before backup and `pg_restore` to rebuild + * the database after restore. + * + * The dump file is written directly to the backup target — no data duplication on disk. + * + * @returns A configured Backups instance with pre/post hooks. Chain `.addVolume()` or + * `.addSync()` to include additional volumes/paths in the backup. + */ + static withPgDump( + config: PgDumpConfig, + ): Backups { + const { + imageId, + dbVolume, + pgdata, + database, + user, + password, + initdbArgs = [], + } = config + const dumpFile = `${BACKUP_CONTAINER_MOUNT}/${database}-db.dump` + const pgMountpoint = pgdata.replace(/\/data$/, '') || pgdata + + function dbMounts() { + return Mounts.of().mountVolume({ + volumeId: dbVolume, + mountpoint: pgMountpoint, + readonly: false, + subpath: null, + }) + } + + async function startPg( + sub: { + exec(cmd: string[], opts?: any): Promise<{ exitCode: number | null }> + execFail( + cmd: string[], + opts?: any, + timeout?: number | null, + ): Promise + }, + label: string, + ) { + await sub.exec(['rm', '-f', `${pgdata}/postmaster.pid`], { + user: 'postgres', + }) + await sub.exec(['mkdir', '-p', '/var/run/postgresql'], { + user: 'root', + }) + await sub.exec(['chown', 'postgres:postgres', '/var/run/postgresql'], { + user: 'root', + }) + console.log(`[${label}] starting postgres`) + await sub.execFail( + ['pg_ctl', 'start', '-D', pgdata, '-o', '-c listen_addresses='], + { user: 'postgres' }, + ) + for (let i = 0; i < 60; i++) { + const { exitCode } = await sub.exec(['pg_isready', '-U', user], { + user: 'postgres', + }) + if (exitCode === 0) { + console.log(`[${label}] postgres is ready`) + return + } + await new Promise((r) => setTimeout(r, 1000)) + } + throw new Error('PostgreSQL failed to become ready within 60 seconds') + } + + return new Backups() + .setPreBackup(async (effects) => { + await SubContainerRc.withTemp( + effects, + { imageId }, + dbMounts() as any, + 'pg-dump', + async (sub) => { + console.log('[pg-dump] mounting backup target') + await mountBackupTarget(sub.rootfs) + await startPg(sub, 'pg-dump') + console.log('[pg-dump] dumping database') + await sub.execFail( + ['pg_dump', '-U', user, '-Fc', '-f', dumpFile, database], + { user: 'postgres' }, + null, + ) + console.log('[pg-dump] stopping postgres') + await sub.execFail(['pg_ctl', 'stop', '-D', pgdata, '-w'], { + user: 'postgres', + }) + console.log('[pg-dump] complete') + }, + ) + }) + .setPostRestore(async (effects) => { + const resolvedPassword = await resolvePassword(password) + await SubContainerRc.withTemp( + effects, + { imageId }, + dbMounts() as any, + 'pg-restore', + async (sub) => { + await mountBackupTarget(sub.rootfs) + await sub.execFail( + ['initdb', '-D', pgdata, '-U', user, ...initdbArgs], + { user: 'postgres' }, + ) + await startPg(sub, 'pg-restore') + await sub.execFail(['createdb', '-U', user, database], { + user: 'postgres', + }) + await sub.execFail( + [ + 'pg_restore', + '-U', + user, + '-d', + database, + '--no-owner', + dumpFile, + ], + { user: 'postgres' }, + null, + ) + await sub.execFail( + [ + 'psql', + '-U', + user, + '-d', + database, + '-c', + `ALTER USER ${user} WITH PASSWORD '${resolvedPassword}'`, + ], + { user: 'postgres' }, + ) + await sub.execFail(['pg_ctl', 'stop', '-D', pgdata, '-w'], { + user: 'postgres', + }) + }, + ) + }) + } + + /** + * Configure MySQL/MariaDB dump-based backup for a volume. + * + * Instead of rsyncing the raw MySQL data directory (which is slow and error-prone), + * this uses `mysqldump` to create a logical dump before backup and `mysql` to restore + * the database after restore. + * + * The dump file is stored temporarily in `dumpVolume` during backup and cleaned up afterward. + * + * @returns A configured Backups instance with pre/post hooks. Chain `.addVolume()` or + * `.addSync()` to include additional volumes/paths in the backup. + */ + static withMysqlDump( + config: MysqlDumpConfig, + ): Backups { + const { + imageId, + dbVolume, + datadir, + database, + user, + password, + engine, + readyCommand, + } = config + const dumpFile = `${BACKUP_CONTAINER_MOUNT}/${database}-db.dump` + + function dbMounts() { + return Mounts.of().mountVolume({ + volumeId: dbVolume, + mountpoint: datadir, + readonly: false, + subpath: null, + }) + } + + async function waitForMysql( + sub: { exec(cmd: string[]): Promise<{ exitCode: number | null }> }, + cmd: string[], + ) { + for (let i = 0; i < 30; i++) { + const { exitCode } = await sub.exec(cmd) + if (exitCode === 0) return + await new Promise((r) => setTimeout(r, 1000)) + } + throw new Error('MySQL/MariaDB failed to become ready within 30 seconds') + } + + return new Backups() + .setPreBackup(async (effects) => { + const pw = await resolvePassword(password) + const readyCmd = readyCommand || [ + 'mysqladmin', + 'ping', + '-u', + user, + `-p${pw}`, + '--silent', + ] + await SubContainerRc.withTemp( + effects, + { imageId }, + dbMounts() as any, + 'mysql-dump', + async (sub) => { + await mountBackupTarget(sub.rootfs) + await sub.exec(['mkdir', '-p', '/var/run/mysqld'], { + user: 'root', + }) + await sub.exec(['chown', 'mysql:mysql', '/var/run/mysqld'], { + user: 'root', + }) + if (engine === 'mysql') { + await sub.execFail(['chown', '-R', 'mysql:mysql', datadir], { + user: 'root', + }) + } + await sub.execFail( + [ + 'mysqld', + '--user=mysql', + `--datadir=${datadir}`, + '--skip-networking', + '--daemonize', + ], + { user: 'root' }, + null, + ) + await waitForMysql(sub, readyCmd) + await sub.execFail( + [ + 'mysqldump', + '-u', + user, + `-p${pw}`, + '--single-transaction', + `--result-file=${dumpFile}`, + database, + ], + { user: 'root' }, + null, + ) + await sub.execFail( + ['mysqladmin', '-u', user, `-p${pw}`, 'shutdown'], + { user: 'root' }, + ) + }, + ) + }) + .setPostRestore(async (effects) => { + const pw = await resolvePassword(password) + await SubContainerRc.withTemp( + effects, + { imageId }, + dbMounts() as any, + 'mysql-restore', + async (sub) => { + await mountBackupTarget(sub.rootfs) + await sub.exec(['mkdir', '-p', '/var/run/mysqld'], { + user: 'root', + }) + await sub.exec(['chown', 'mysql:mysql', '/var/run/mysqld'], { + user: 'root', + }) + // Initialize fresh data directory + if (engine === 'mariadb') { + await sub.execFail( + ['mysql_install_db', '--user=mysql', `--datadir=${datadir}`], + { user: 'root' }, + ) + } else { + await sub.execFail( + [ + 'mysqld', + '--initialize-insecure', + '--user=mysql', + `--datadir=${datadir}`, + ], + { user: 'root' }, + ) + } + await sub.execFail( + [ + 'mysqld', + '--user=mysql', + `--datadir=${datadir}`, + '--skip-networking', + '--daemonize', + ], + { user: 'root' }, + null, + ) + // After fresh init, root has no password + await waitForMysql(sub, [ + 'mysqladmin', + 'ping', + '-u', + 'root', + '--silent', + ]) + // Create database, user, and set password + await sub.execFail( + [ + 'mysql', + '-u', + 'root', + '-e', + `CREATE DATABASE IF NOT EXISTS \`${database}\`; CREATE USER IF NOT EXISTS '${user}'@'localhost' IDENTIFIED BY '${pw}'; GRANT ALL ON \`${database}\`.* TO '${user}'@'localhost'; ALTER USER 'root'@'localhost' IDENTIFIED BY '${pw}'; FLUSH PRIVILEGES;`, + ], + { user: 'root' }, + ) + // Restore from dump + await sub.execFail( + [ + 'sh', + '-c', + `mysql -u root -p'${pw}' \`${database}\` < ${dumpFile}`, + ], + { user: 'root' }, + null, + ) + await sub.execFail( + ['mysqladmin', '-u', 'root', `-p${password}`, 'shutdown'], + { user: 'root' }, + ) + }, + ) + }) + } + /** * Override the default rsync options for both backup and restore. * @param options - Partial rsync options to merge with current defaults diff --git a/sdk/package/lib/index.ts b/sdk/package/lib/index.ts index 06f99b915..879aa978b 100644 --- a/sdk/package/lib/index.ts +++ b/sdk/package/lib/index.ts @@ -32,6 +32,7 @@ export { setupManifest, buildManifest } from './manifest/setupManifest' export { FileHelper } from './util/fileHelper' export { smtpShape, + smtpPrefill, type SmtpSelection, } from '../../base/lib/actions/input/inputSpecConstants' diff --git a/sdk/package/package-lock.json b/sdk/package/package-lock.json index fa173dd37..a86d64a29 100644 --- a/sdk/package/package-lock.json +++ b/sdk/package/package-lock.json @@ -1,12 +1,12 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.63", + "version": "0.4.0-beta.64", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.63", + "version": "0.4.0-beta.64", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", diff --git a/sdk/package/package.json b/sdk/package/package.json index 0870f5259..4680a58db 100644 --- a/sdk/package/package.json +++ b/sdk/package/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.63", + "version": "0.4.0-beta.64", "description": "Software development kit to facilitate packaging services for StartOS", "main": "./package/lib/index.js", "types": "./package/lib/index.d.ts", From 25aa1401746f9cd85c3473b272d21fc6b1c7b35a Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Sun, 22 Mar 2026 23:55:26 -0600 Subject: [PATCH 46/53] fix: backup status reporting --- container-runtime/package-lock.json | 2 +- core/src/service/mod.rs | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/container-runtime/package-lock.json b/container-runtime/package-lock.json index 31478b8f4..7814fa09b 100644 --- a/container-runtime/package-lock.json +++ b/container-runtime/package-lock.json @@ -37,7 +37,7 @@ }, "../sdk/dist": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.62", + "version": "0.4.0-beta.64", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", diff --git a/core/src/service/mod.rs b/core/src/service/mod.rs index 9fbcfa300..b11e81859 100644 --- a/core/src/service/mod.rs +++ b/core/src/service/mod.rs @@ -673,16 +673,8 @@ impl Service { #[instrument(skip_all)] pub async fn backup(&self, guard: impl GenericMountGuard) -> Result<(), Error> { let id = &self.seed.id; - let mut file = - AtomicFile::new(guard.path().join(id).with_extension("s9pk"), None::<&str>).await?; - self.seed - .persistent_container - .s9pk - .clone() - .serialize(&mut *file, true) - .await?; - file.save().await?; - // TODO: reverify? + // Prepare the backup future in the actor first, so the cell is + // populated before the actor reacts to the DesiredStatus change. let backup = self .actor .send( @@ -692,6 +684,8 @@ impl Service { }, ) .await??; + // Set status early so the UI reflects "backing up" while the s9pk + // serialization and service stop happen concurrently. self.seed .ctx .db @@ -706,6 +700,15 @@ impl Service { }) .await .result?; + let mut file = + AtomicFile::new(guard.path().join(id).with_extension("s9pk"), None::<&str>).await?; + self.seed + .persistent_container + .s9pk + .clone() + .serialize(&mut *file, true) + .await?; + file.save().await?; backup.await } From b7e4df44bffdea4298ad32819a818952bcf4ef54 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Sun, 22 Mar 2026 23:58:14 -0600 Subject: [PATCH 47/53] wip: subcontainer exec log drain via SCM_RIGHTS (reference only) Implemented pipe FD handoff from exec to launch via Unix socket + SCM_RIGHTS for grandchild log capture. Superseded by the simpler PR_SET_DUMPABLE approach which eliminates the need for pipes entirely. --- core/Cargo.toml | 1 + core/src/service/effects/subcontainer/sync.rs | 355 +++++++++++++++++- 2 files changed, 343 insertions(+), 13 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 77c189f93..4566d666e 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -161,6 +161,7 @@ nix = { version = "0.30.1", features = [ "process", "sched", "signal", + "socket", "user", ] } nom = "8.0.0" diff --git a/core/src/service/effects/subcontainer/sync.rs b/core/src/service/effects/subcontainer/sync.rs index c4d27994a..8b91c33a8 100644 --- a/core/src/service/effects/subcontainer/sync.rs +++ b/core/src/service/effects/subcontainer/sync.rs @@ -1,6 +1,7 @@ use std::ffi::{OsStr, OsString, c_int}; use std::fs::File; use std::io::{BufRead, BufReader, IsTerminal, Read}; +use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd}; use std::os::unix::process::{CommandExt, ExitStatusExt}; use std::path::{Path, PathBuf}; use std::process::{Command as StdCommand, Stdio}; @@ -8,6 +9,9 @@ use std::sync::Arc; use nix::errno::Errno; use nix::sched::CloneFlags; +use nix::sys::socket::{ + recvmsg, sendmsg, ControlMessage, ControlMessageOwned, MsgFlags, +}; use nix::unistd::Pid; use signal_hook::consts::signal::*; use termion::raw::IntoRawMode; @@ -104,6 +108,129 @@ fn open_file_read(path: impl AsRef) -> Result { }) } +const LOG_DRAIN_SOCK: &str = ".log-drain.sock"; + +fn log_drain_sock_path(chroot: &Path) -> PathBuf { + chroot.join(LOG_DRAIN_SOCK) +} + +/// Send file descriptors to the log drain socket via SCM_RIGHTS. +/// Best-effort: silently returns on any failure. +fn send_drain_fds(chroot: &Path, fds: &[RawFd]) { + let sock_path = log_drain_sock_path(chroot); + let stream = match std::os::unix::net::UnixStream::connect(&sock_path) { + Ok(s) => s, + Err(e) => { + tracing::debug!("no log drain socket: {e}"); + return; + } + }; + let cmsg = [ControlMessage::ScmRights(fds)]; + let iov = [std::io::IoSlice::new(&[0u8])]; + if let Err(e) = sendmsg::<()>(stream.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None) { + tracing::warn!("failed to send drain fds: {e}"); + } +} + +/// Receive file descriptors from a Unix stream via SCM_RIGHTS. +fn recv_drain_fds(stream: &std::os::unix::net::UnixStream) -> Result, nix::Error> { + let mut buf = [0u8; 1]; + let mut iov = [std::io::IoSliceMut::new(&mut buf)]; + let mut cmsg_buf = nix::cmsg_space!([RawFd; 4]); + let msg = recvmsg::<()>( + stream.as_raw_fd(), + &mut iov, + Some(&mut cmsg_buf), + MsgFlags::empty(), + )?; + let mut fds = Vec::new(); + for cmsg in msg.cmsgs()? { + if let ControlMessageOwned::ScmRights(received) = cmsg { + for fd in received { + fds.push(unsafe { OwnedFd::from_raw_fd(fd) }); + } + } + } + Ok(fds) +} + +/// Non-blocking drain of the pipe/pty buffer into `out`. The dup'd FD shares +/// the same pipe as the I/O thread, so both consumers write to the caller's +/// stdout/stderr — no data is lost. +fn drain_buffer(fd: &OwnedFd, out: &mut impl std::io::Write) { + use std::os::fd::AsFd; + let flags = nix::fcntl::fcntl(fd.as_fd(), nix::fcntl::FcntlArg::F_GETFL).unwrap_or(0); + let _ = nix::fcntl::fcntl( + fd.as_fd(), + nix::fcntl::FcntlArg::F_SETFL( + nix::fcntl::OFlag::from_bits_truncate(flags) | nix::fcntl::OFlag::O_NONBLOCK, + ), + ); + let mut buf = [0u8; CAP_1_KiB]; + loop { + match nix::unistd::read(fd.as_fd(), &mut buf) { + Ok(0) | Err(Errno::EAGAIN) | Err(_) => break, + Ok(n) => { + out.write_all(&buf[..n]).ok(); + } + } + } + out.flush().ok(); + let _ = nix::fcntl::fcntl( + fd.as_fd(), + nix::fcntl::FcntlArg::F_SETFL(nix::fcntl::OFlag::from_bits_truncate(flags)), + ); +} + +/// Start a Unix socket listener that accepts FD handoffs from `exec` processes. +/// Received FDs are drained to stderr (which flows to container-runtime's journald). +fn start_drain_listener(chroot: &Path) { + use std::io::{Read, Write}; + use std::os::unix::net::UnixListener; + + let sock_path = log_drain_sock_path(chroot); + let _ = std::fs::remove_file(&sock_path); + let listener = match UnixListener::bind(&sock_path) { + Ok(l) => l, + Err(e) => { + tracing::warn!("failed to bind log drain socket: {e}"); + return; + } + }; + + std::thread::spawn(move || { + for stream in listener.incoming() { + let stream = match stream { + Ok(s) => s, + Err(_) => break, + }; + match recv_drain_fds(&stream) { + Ok(fds) => { + for fd in fds { + std::thread::spawn(move || { + let mut reader = File::from(fd); + let mut buf = [0u8; CAP_1_KiB]; + loop { + match reader.read(&mut buf) { + Ok(0) | Err(_) => break, + Ok(n) => { + let stderr = std::io::stderr(); + let mut out = stderr.lock(); + out.write_all(&buf[..n]).ok(); + } + } + } + }); + } + } + Err(e) => { + tracing::warn!("failed to receive drain fds: {e}"); + } + } + } + }); +} + #[derive(Debug, Clone, Serialize, Deserialize, Parser)] #[group(skip)] pub struct ExecParams { @@ -331,6 +458,7 @@ pub fn launch( use std::io::Write; kill_init(Path::new("/proc"), &chroot)?; + start_drain_listener(&chroot); let mut sig = signal_hook::iterator::Signals::new(FWD_SIGNALS)?; let (send_pid, recv_pid) = oneshot::channel(); std::thread::spawn(move || { @@ -507,8 +635,6 @@ pub fn launch( stderr_send .send(Box::new(child.stderr.take().unwrap())) .unwrap_or_default(); - - // TODO: subreaping, signal handling let exit = child .wait() .with_ctx(|_| (ErrorKind::Filesystem, "waiting on child process"))?; @@ -628,7 +754,7 @@ pub fn exec( } }); let (stdout_send, stdout_recv) = oneshot::channel::>(); - let stdout_thread = std::thread::spawn(move || { + let _stdout_thread = std::thread::spawn(move || { if let Ok(mut cstdout) = stdout_recv.blocking_recv() { if tty { let mut stdout = stdout.lock(); @@ -646,7 +772,7 @@ pub fn exec( } }); let (stderr_send, stderr_recv) = oneshot::channel::>(); - let stderr_thread = if !stderr_tty { + let _stderr_thread = if !stderr_tty { Some(std::thread::spawn(move || { if let Ok(mut cstderr) = stderr_recv.blocking_recv() { std::io::copy(&mut cstderr, &mut stderr.lock()).unwrap(); @@ -705,6 +831,18 @@ pub fn exec( }; pty.resize(size).with_kind(ErrorKind::Filesystem)?; } + + // Dup the PTY master (and separate stderr if piped) for drain handoff + let pty_drain = nix::unistd::dup(&pty) + .with_ctx(|_| (ErrorKind::Filesystem, "dup pty for drain"))?; + let mut drain_fds = vec![pty_drain]; + if let Some(stderr) = child.stderr.take() { + let stderr_drain = nix::unistd::dup(&stderr) + .with_ctx(|_| (ErrorKind::Filesystem, "dup stderr for drain"))?; + drain_fds.push(stderr_drain); + stderr_send.send(Box::new(stderr)).unwrap_or_default(); + } + let shared = ArcPty(Arc::new(pty)); stdin_send .send(Box::new(shared.clone())) @@ -712,14 +850,23 @@ pub fn exec( stdout_send .send(Box::new(shared.clone())) .unwrap_or_default(); - if let Some(stderr) = child.stderr.take() { - stderr_send.send(Box::new(stderr)).unwrap_or_default(); - } + let exit = child .wait() .with_ctx(|_| (ErrorKind::Filesystem, "waiting on child process"))?; - stdout_thread.join().unwrap(); - stderr_thread.map(|t| t.join().unwrap()); + + // Flush any remaining pipe buffer data to the caller, then hand off + // the dup'd FDs to launch for grandchild log capture. + // We cannot join the I/O threads because grandchildren may hold the + // pipe write ends open indefinitely. + drain_buffer(&drain_fds[0], &mut std::io::stdout().lock()); + if drain_fds.len() > 1 { + drain_buffer(&drain_fds[1], &mut std::io::stderr().lock()); + } + let raw_fds: Vec = drain_fds.iter().map(|fd| fd.as_raw_fd()).collect(); + send_drain_fds(&chroot, &raw_fds); + drop(drain_fds); + if let Some(code) = exit.code() { drop(raw); std::process::exit(code); @@ -756,20 +903,40 @@ pub fn exec( .map_err(color_eyre::eyre::Report::msg) .with_ctx(|_| (ErrorKind::Filesystem, "spawning child process"))?; send_pid.send(child.id() as i32).unwrap_or_default(); + + // Take pipe handles and dup them for later handoff to the drain listener. + // We dup before sending the originals to I/O threads. + let child_stdout = child.stdout.take().unwrap(); + let child_stderr = child.stderr.take().unwrap(); + let stdout_drain = nix::unistd::dup(&child_stdout) + .with_ctx(|_| (ErrorKind::Filesystem, "dup stdout for drain"))?; + let stderr_drain = nix::unistd::dup(&child_stderr) + .with_ctx(|_| (ErrorKind::Filesystem, "dup stderr for drain"))?; + stdin_send .send(Box::new(child.stdin.take().unwrap())) .unwrap_or_default(); stdout_send - .send(Box::new(child.stdout.take().unwrap())) + .send(Box::new(child_stdout)) .unwrap_or_default(); stderr_send - .send(Box::new(child.stderr.take().unwrap())) + .send(Box::new(child_stderr)) .unwrap_or_default(); + let exit = child .wait() .with_ctx(|_| (ErrorKind::Filesystem, "waiting on child process"))?; - stdout_thread.join().unwrap(); - stderr_thread.map(|t| t.join().unwrap()); + + // Flush any remaining pipe buffer data to the caller, then hand off + // the dup'd FDs to launch for grandchild log capture. + // We cannot join the I/O threads because grandchildren may hold the + // pipe write ends open indefinitely. + drain_buffer(&stdout_drain, &mut std::io::stdout().lock()); + drain_buffer(&stderr_drain, &mut std::io::stderr().lock()); + send_drain_fds(&chroot, &[stdout_drain.as_raw_fd(), stderr_drain.as_raw_fd()]); + drop(stdout_drain); + drop(stderr_drain); + if let Some(code) = exit.code() { std::process::exit(code); } else if exit.success() || exit.signal() == Some(15) { @@ -786,3 +953,165 @@ pub fn exec( pub fn exec_command(_: ContainerCliContext, params: ExecParams) -> Result<(), Error> { params.exec() } + +#[cfg(test)] +mod tests { + use super::*; + use std::io::Write; + use std::os::fd::AsFd; + use std::os::unix::net::UnixListener; + use std::sync::atomic::{AtomicU32, Ordering}; + + static TEST_COUNTER: AtomicU32 = AtomicU32::new(0); + + fn test_dir() -> PathBuf { + let n = TEST_COUNTER.fetch_add(1, Ordering::Relaxed); + let dir = std::env::temp_dir().join(format!( + "startos-test-drain-{}-{}", + std::process::id(), + n, + )); + std::fs::create_dir_all(&dir).unwrap(); + dir + } + + /// Create an anonymous pipe, returning (read_end, write_end) as OwnedFds. + fn pipe() -> (OwnedFd, OwnedFd) { + let (r, w) = nix::unistd::pipe().unwrap(); + (r, w) + } + + #[test] + fn test_send_recv_drain_fds() { + let dir = test_dir(); + let sock_path = dir.join(LOG_DRAIN_SOCK); + let listener = UnixListener::bind(&sock_path).unwrap(); + + let (pipe_r, pipe_w) = pipe(); + let raw_fd = pipe_r.as_raw_fd(); + + // Send the read end of the pipe + let send_thread = std::thread::spawn(move || { + let stream = std::os::unix::net::UnixStream::connect(&sock_path).unwrap(); + let cmsg = [ControlMessage::ScmRights(&[raw_fd])]; + let iov = [std::io::IoSlice::new(&[0u8])]; + sendmsg::<()>(stream.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap(); + drop(pipe_r); // close our copy after sending + }); + + // Receive on the listener side + let (stream, _) = listener.accept().unwrap(); + let fds = recv_drain_fds(&stream).unwrap(); + send_thread.join().unwrap(); + + assert_eq!(fds.len(), 1, "should receive exactly one FD"); + + // Write through the pipe and read from the received FD + let mut writer = File::from(pipe_w); + writer.write_all(b"hello from pipe").unwrap(); + drop(writer); + + let mut reader = File::from(fds.into_iter().next().unwrap()); + let mut buf = String::new(); + std::io::Read::read_to_string(&mut reader, &mut buf).unwrap(); + assert_eq!(buf, "hello from pipe"); + } + + #[test] + fn test_drain_buffer_reads_available_data() { + let (pipe_r, pipe_w) = pipe(); + + let mut writer = File::from(pipe_w); + writer.write_all(b"buffered data").unwrap(); + drop(writer); + + let mut output = Vec::new(); + drain_buffer(&pipe_r, &mut output); + + assert_eq!(output, b"buffered data"); + } + + #[test] + fn test_drain_buffer_returns_immediately_on_empty_pipe() { + let (pipe_r, _pipe_w) = pipe(); + + // Pipe is open but empty — should return immediately (EAGAIN) + let mut output = Vec::new(); + drain_buffer(&pipe_r, &mut output); + + assert!(output.is_empty(), "empty pipe should yield no data"); + } + + #[test] + fn test_drain_buffer_restores_blocking_mode() { + let (pipe_r, _pipe_w) = pipe(); + + let flags_before = + nix::fcntl::fcntl(pipe_r.as_fd(), nix::fcntl::FcntlArg::F_GETFL).unwrap(); + drain_buffer(&pipe_r, &mut Vec::new()); + let flags_after = + nix::fcntl::fcntl(pipe_r.as_fd(), nix::fcntl::FcntlArg::F_GETFL).unwrap(); + + assert_eq!(flags_before, flags_after, "flags should be restored"); + } + + #[test] + fn test_dup_preserves_pipe_after_original_closed() { + // Simulates the real flow: dup the pipe, close the original, + // verify data is still readable from the dup'd FD. + let (pipe_r, pipe_w) = pipe(); + + let drain_fd = nix::unistd::dup(pipe_r.as_fd()).unwrap(); + + let mut writer = File::from(pipe_w); + writer.write_all(b"child output").unwrap(); + drop(writer); + + // Close original — pipe stays alive through drain_fd + drop(pipe_r); + + let mut reader = File::from(drain_fd); + let mut buf = String::new(); + std::io::Read::read_to_string(&mut reader, &mut buf).unwrap(); + assert_eq!(buf, "child output"); + } + + #[test] + fn test_start_drain_listener_end_to_end() { + // Full integration: start the listener, send a pipe FD, write data, + // verify the listener drains it. + let chroot = test_dir(); + + start_drain_listener(&chroot); + + // Give the listener thread a moment to bind + std::thread::sleep(std::time::Duration::from_millis(50)); + + let (pipe_r, pipe_w) = pipe(); + + // Send the pipe read end to the drain listener + send_drain_fds(&chroot, &[pipe_r.as_raw_fd()]); + drop(pipe_r); // close our copy; listener has its own + + // Write data — the listener should drain it (to stderr in production, + // but we just verify the pipe doesn't block/hang) + let mut writer = File::from(pipe_w); + for _ in 0..100 { + writer.write_all(b"log line\n").unwrap(); + } + drop(writer); + + // Give the drain thread time to process + std::thread::sleep(std::time::Duration::from_millis(100)); + // If we get here without hanging, the test passes. + } + + #[test] + fn test_send_drain_fds_no_socket_does_not_panic() { + // When no drain socket exists, send_drain_fds should silently return + let dir = test_dir(); + let (pipe_r, _pipe_w) = pipe(); + send_drain_fds(&dir, &[pipe_r.as_raw_fd()]); + // No panic, no error — best-effort + } +} From 8d1e11e158a69051ce641f434de8bb24eff6dc76 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 23 Mar 2026 01:13:20 -0600 Subject: [PATCH 48/53] fix: pg_dump/pg_restore permission errors in backup subcontainer - Pre-create and chown dump file for postgres user before pg_dump - Chown volume mountpoint to postgres before initdb on restore - Add --no-privileges to pg_restore to skip GRANT/REVOKE for missing roles --- core/Cargo.toml | 1 - core/src/service/effects/subcontainer/sync.rs | 370 +----------------- sdk/package/lib/backup/Backups.ts | 9 + 3 files changed, 20 insertions(+), 360 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 4566d666e..77c189f93 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -161,7 +161,6 @@ nix = { version = "0.30.1", features = [ "process", "sched", "signal", - "socket", "user", ] } nom = "8.0.0" diff --git a/core/src/service/effects/subcontainer/sync.rs b/core/src/service/effects/subcontainer/sync.rs index 8b91c33a8..e1205a1a1 100644 --- a/core/src/service/effects/subcontainer/sync.rs +++ b/core/src/service/effects/subcontainer/sync.rs @@ -1,7 +1,6 @@ use std::ffi::{OsStr, OsString, c_int}; use std::fs::File; use std::io::{BufRead, BufReader, IsTerminal, Read}; -use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd}; use std::os::unix::process::{CommandExt, ExitStatusExt}; use std::path::{Path, PathBuf}; use std::process::{Command as StdCommand, Stdio}; @@ -9,9 +8,6 @@ use std::sync::Arc; use nix::errno::Errno; use nix::sched::CloneFlags; -use nix::sys::socket::{ - recvmsg, sendmsg, ControlMessage, ControlMessageOwned, MsgFlags, -}; use nix::unistd::Pid; use signal_hook::consts::signal::*; use termion::raw::IntoRawMode; @@ -108,129 +104,6 @@ fn open_file_read(path: impl AsRef) -> Result { }) } -const LOG_DRAIN_SOCK: &str = ".log-drain.sock"; - -fn log_drain_sock_path(chroot: &Path) -> PathBuf { - chroot.join(LOG_DRAIN_SOCK) -} - -/// Send file descriptors to the log drain socket via SCM_RIGHTS. -/// Best-effort: silently returns on any failure. -fn send_drain_fds(chroot: &Path, fds: &[RawFd]) { - let sock_path = log_drain_sock_path(chroot); - let stream = match std::os::unix::net::UnixStream::connect(&sock_path) { - Ok(s) => s, - Err(e) => { - tracing::debug!("no log drain socket: {e}"); - return; - } - }; - let cmsg = [ControlMessage::ScmRights(fds)]; - let iov = [std::io::IoSlice::new(&[0u8])]; - if let Err(e) = sendmsg::<()>(stream.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None) { - tracing::warn!("failed to send drain fds: {e}"); - } -} - -/// Receive file descriptors from a Unix stream via SCM_RIGHTS. -fn recv_drain_fds(stream: &std::os::unix::net::UnixStream) -> Result, nix::Error> { - let mut buf = [0u8; 1]; - let mut iov = [std::io::IoSliceMut::new(&mut buf)]; - let mut cmsg_buf = nix::cmsg_space!([RawFd; 4]); - let msg = recvmsg::<()>( - stream.as_raw_fd(), - &mut iov, - Some(&mut cmsg_buf), - MsgFlags::empty(), - )?; - let mut fds = Vec::new(); - for cmsg in msg.cmsgs()? { - if let ControlMessageOwned::ScmRights(received) = cmsg { - for fd in received { - fds.push(unsafe { OwnedFd::from_raw_fd(fd) }); - } - } - } - Ok(fds) -} - -/// Non-blocking drain of the pipe/pty buffer into `out`. The dup'd FD shares -/// the same pipe as the I/O thread, so both consumers write to the caller's -/// stdout/stderr — no data is lost. -fn drain_buffer(fd: &OwnedFd, out: &mut impl std::io::Write) { - use std::os::fd::AsFd; - let flags = nix::fcntl::fcntl(fd.as_fd(), nix::fcntl::FcntlArg::F_GETFL).unwrap_or(0); - let _ = nix::fcntl::fcntl( - fd.as_fd(), - nix::fcntl::FcntlArg::F_SETFL( - nix::fcntl::OFlag::from_bits_truncate(flags) | nix::fcntl::OFlag::O_NONBLOCK, - ), - ); - let mut buf = [0u8; CAP_1_KiB]; - loop { - match nix::unistd::read(fd.as_fd(), &mut buf) { - Ok(0) | Err(Errno::EAGAIN) | Err(_) => break, - Ok(n) => { - out.write_all(&buf[..n]).ok(); - } - } - } - out.flush().ok(); - let _ = nix::fcntl::fcntl( - fd.as_fd(), - nix::fcntl::FcntlArg::F_SETFL(nix::fcntl::OFlag::from_bits_truncate(flags)), - ); -} - -/// Start a Unix socket listener that accepts FD handoffs from `exec` processes. -/// Received FDs are drained to stderr (which flows to container-runtime's journald). -fn start_drain_listener(chroot: &Path) { - use std::io::{Read, Write}; - use std::os::unix::net::UnixListener; - - let sock_path = log_drain_sock_path(chroot); - let _ = std::fs::remove_file(&sock_path); - let listener = match UnixListener::bind(&sock_path) { - Ok(l) => l, - Err(e) => { - tracing::warn!("failed to bind log drain socket: {e}"); - return; - } - }; - - std::thread::spawn(move || { - for stream in listener.incoming() { - let stream = match stream { - Ok(s) => s, - Err(_) => break, - }; - match recv_drain_fds(&stream) { - Ok(fds) => { - for fd in fds { - std::thread::spawn(move || { - let mut reader = File::from(fd); - let mut buf = [0u8; CAP_1_KiB]; - loop { - match reader.read(&mut buf) { - Ok(0) | Err(_) => break, - Ok(n) => { - let stderr = std::io::stderr(); - let mut out = stderr.lock(); - out.write_all(&buf[..n]).ok(); - } - } - } - }); - } - } - Err(e) => { - tracing::warn!("failed to receive drain fds: {e}"); - } - } - } - }); -} - #[derive(Debug, Clone, Serialize, Deserialize, Parser)] #[group(skip)] pub struct ExecParams { @@ -396,13 +269,6 @@ impl ExecParams { std::os::unix::fs::chroot(chroot) .with_ctx(|_| (ErrorKind::Filesystem, lazy_format!("chroot {chroot:?}")))?; - if let Ok(uid) = uid { - if uid != 0 { - std::os::unix::fs::chown("/proc/self/fd/0", Some(uid), gid.ok()).ok(); - std::os::unix::fs::chown("/proc/self/fd/1", Some(uid), gid.ok()).ok(); - std::os::unix::fs::chown("/proc/self/fd/2", Some(uid), gid.ok()).ok(); - } - } // Handle credential changes in pre_exec to control the order: // setgroups must happen before setgid/setuid (requires CAP_SETGID) { @@ -426,6 +292,10 @@ impl ExecParams { nix::unistd::setuid(nix::unistd::Uid::from_raw(uid)) .map_err(|e| std::io::Error::from_raw_os_error(e as i32))?; } + // Restore dumpable flag cleared by setuid so that + // /proc/self/fd/* is owned by the current uid and + // /dev/stderr works for the target user. + libc::prctl(libc::PR_SET_DUMPABLE, 1, 0, 0, 0); Ok(()) }); } @@ -458,7 +328,6 @@ pub fn launch( use std::io::Write; kill_init(Path::new("/proc"), &chroot)?; - start_drain_listener(&chroot); let mut sig = signal_hook::iterator::Signals::new(FWD_SIGNALS)?; let (send_pid, recv_pid) = oneshot::channel(); std::thread::spawn(move || { @@ -754,7 +623,7 @@ pub fn exec( } }); let (stdout_send, stdout_recv) = oneshot::channel::>(); - let _stdout_thread = std::thread::spawn(move || { + let stdout_thread = std::thread::spawn(move || { if let Ok(mut cstdout) = stdout_recv.blocking_recv() { if tty { let mut stdout = stdout.lock(); @@ -772,7 +641,7 @@ pub fn exec( } }); let (stderr_send, stderr_recv) = oneshot::channel::>(); - let _stderr_thread = if !stderr_tty { + let stderr_thread = if !stderr_tty { Some(std::thread::spawn(move || { if let Ok(mut cstderr) = stderr_recv.blocking_recv() { std::io::copy(&mut cstderr, &mut stderr.lock()).unwrap(); @@ -831,18 +700,6 @@ pub fn exec( }; pty.resize(size).with_kind(ErrorKind::Filesystem)?; } - - // Dup the PTY master (and separate stderr if piped) for drain handoff - let pty_drain = nix::unistd::dup(&pty) - .with_ctx(|_| (ErrorKind::Filesystem, "dup pty for drain"))?; - let mut drain_fds = vec![pty_drain]; - if let Some(stderr) = child.stderr.take() { - let stderr_drain = nix::unistd::dup(&stderr) - .with_ctx(|_| (ErrorKind::Filesystem, "dup stderr for drain"))?; - drain_fds.push(stderr_drain); - stderr_send.send(Box::new(stderr)).unwrap_or_default(); - } - let shared = ArcPty(Arc::new(pty)); stdin_send .send(Box::new(shared.clone())) @@ -850,23 +707,14 @@ pub fn exec( stdout_send .send(Box::new(shared.clone())) .unwrap_or_default(); - + if let Some(stderr) = child.stderr.take() { + stderr_send.send(Box::new(stderr)).unwrap_or_default(); + } let exit = child .wait() .with_ctx(|_| (ErrorKind::Filesystem, "waiting on child process"))?; - - // Flush any remaining pipe buffer data to the caller, then hand off - // the dup'd FDs to launch for grandchild log capture. - // We cannot join the I/O threads because grandchildren may hold the - // pipe write ends open indefinitely. - drain_buffer(&drain_fds[0], &mut std::io::stdout().lock()); - if drain_fds.len() > 1 { - drain_buffer(&drain_fds[1], &mut std::io::stderr().lock()); - } - let raw_fds: Vec = drain_fds.iter().map(|fd| fd.as_raw_fd()).collect(); - send_drain_fds(&chroot, &raw_fds); - drop(drain_fds); - + stdout_thread.join().unwrap(); + stderr_thread.map(|t| t.join().unwrap()); if let Some(code) = exit.code() { drop(raw); std::process::exit(code); @@ -895,48 +743,14 @@ pub fn exec( } cmd.arg(&chroot); cmd.args(&command); - cmd.stdin(Stdio::piped()); - cmd.stdout(Stdio::piped()); - cmd.stderr(Stdio::piped()); let mut child = cmd .spawn() .map_err(color_eyre::eyre::Report::msg) .with_ctx(|_| (ErrorKind::Filesystem, "spawning child process"))?; send_pid.send(child.id() as i32).unwrap_or_default(); - - // Take pipe handles and dup them for later handoff to the drain listener. - // We dup before sending the originals to I/O threads. - let child_stdout = child.stdout.take().unwrap(); - let child_stderr = child.stderr.take().unwrap(); - let stdout_drain = nix::unistd::dup(&child_stdout) - .with_ctx(|_| (ErrorKind::Filesystem, "dup stdout for drain"))?; - let stderr_drain = nix::unistd::dup(&child_stderr) - .with_ctx(|_| (ErrorKind::Filesystem, "dup stderr for drain"))?; - - stdin_send - .send(Box::new(child.stdin.take().unwrap())) - .unwrap_or_default(); - stdout_send - .send(Box::new(child_stdout)) - .unwrap_or_default(); - stderr_send - .send(Box::new(child_stderr)) - .unwrap_or_default(); - let exit = child .wait() .with_ctx(|_| (ErrorKind::Filesystem, "waiting on child process"))?; - - // Flush any remaining pipe buffer data to the caller, then hand off - // the dup'd FDs to launch for grandchild log capture. - // We cannot join the I/O threads because grandchildren may hold the - // pipe write ends open indefinitely. - drain_buffer(&stdout_drain, &mut std::io::stdout().lock()); - drain_buffer(&stderr_drain, &mut std::io::stderr().lock()); - send_drain_fds(&chroot, &[stdout_drain.as_raw_fd(), stderr_drain.as_raw_fd()]); - drop(stdout_drain); - drop(stderr_drain); - if let Some(code) = exit.code() { std::process::exit(code); } else if exit.success() || exit.signal() == Some(15) { @@ -953,165 +767,3 @@ pub fn exec( pub fn exec_command(_: ContainerCliContext, params: ExecParams) -> Result<(), Error> { params.exec() } - -#[cfg(test)] -mod tests { - use super::*; - use std::io::Write; - use std::os::fd::AsFd; - use std::os::unix::net::UnixListener; - use std::sync::atomic::{AtomicU32, Ordering}; - - static TEST_COUNTER: AtomicU32 = AtomicU32::new(0); - - fn test_dir() -> PathBuf { - let n = TEST_COUNTER.fetch_add(1, Ordering::Relaxed); - let dir = std::env::temp_dir().join(format!( - "startos-test-drain-{}-{}", - std::process::id(), - n, - )); - std::fs::create_dir_all(&dir).unwrap(); - dir - } - - /// Create an anonymous pipe, returning (read_end, write_end) as OwnedFds. - fn pipe() -> (OwnedFd, OwnedFd) { - let (r, w) = nix::unistd::pipe().unwrap(); - (r, w) - } - - #[test] - fn test_send_recv_drain_fds() { - let dir = test_dir(); - let sock_path = dir.join(LOG_DRAIN_SOCK); - let listener = UnixListener::bind(&sock_path).unwrap(); - - let (pipe_r, pipe_w) = pipe(); - let raw_fd = pipe_r.as_raw_fd(); - - // Send the read end of the pipe - let send_thread = std::thread::spawn(move || { - let stream = std::os::unix::net::UnixStream::connect(&sock_path).unwrap(); - let cmsg = [ControlMessage::ScmRights(&[raw_fd])]; - let iov = [std::io::IoSlice::new(&[0u8])]; - sendmsg::<()>(stream.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap(); - drop(pipe_r); // close our copy after sending - }); - - // Receive on the listener side - let (stream, _) = listener.accept().unwrap(); - let fds = recv_drain_fds(&stream).unwrap(); - send_thread.join().unwrap(); - - assert_eq!(fds.len(), 1, "should receive exactly one FD"); - - // Write through the pipe and read from the received FD - let mut writer = File::from(pipe_w); - writer.write_all(b"hello from pipe").unwrap(); - drop(writer); - - let mut reader = File::from(fds.into_iter().next().unwrap()); - let mut buf = String::new(); - std::io::Read::read_to_string(&mut reader, &mut buf).unwrap(); - assert_eq!(buf, "hello from pipe"); - } - - #[test] - fn test_drain_buffer_reads_available_data() { - let (pipe_r, pipe_w) = pipe(); - - let mut writer = File::from(pipe_w); - writer.write_all(b"buffered data").unwrap(); - drop(writer); - - let mut output = Vec::new(); - drain_buffer(&pipe_r, &mut output); - - assert_eq!(output, b"buffered data"); - } - - #[test] - fn test_drain_buffer_returns_immediately_on_empty_pipe() { - let (pipe_r, _pipe_w) = pipe(); - - // Pipe is open but empty — should return immediately (EAGAIN) - let mut output = Vec::new(); - drain_buffer(&pipe_r, &mut output); - - assert!(output.is_empty(), "empty pipe should yield no data"); - } - - #[test] - fn test_drain_buffer_restores_blocking_mode() { - let (pipe_r, _pipe_w) = pipe(); - - let flags_before = - nix::fcntl::fcntl(pipe_r.as_fd(), nix::fcntl::FcntlArg::F_GETFL).unwrap(); - drain_buffer(&pipe_r, &mut Vec::new()); - let flags_after = - nix::fcntl::fcntl(pipe_r.as_fd(), nix::fcntl::FcntlArg::F_GETFL).unwrap(); - - assert_eq!(flags_before, flags_after, "flags should be restored"); - } - - #[test] - fn test_dup_preserves_pipe_after_original_closed() { - // Simulates the real flow: dup the pipe, close the original, - // verify data is still readable from the dup'd FD. - let (pipe_r, pipe_w) = pipe(); - - let drain_fd = nix::unistd::dup(pipe_r.as_fd()).unwrap(); - - let mut writer = File::from(pipe_w); - writer.write_all(b"child output").unwrap(); - drop(writer); - - // Close original — pipe stays alive through drain_fd - drop(pipe_r); - - let mut reader = File::from(drain_fd); - let mut buf = String::new(); - std::io::Read::read_to_string(&mut reader, &mut buf).unwrap(); - assert_eq!(buf, "child output"); - } - - #[test] - fn test_start_drain_listener_end_to_end() { - // Full integration: start the listener, send a pipe FD, write data, - // verify the listener drains it. - let chroot = test_dir(); - - start_drain_listener(&chroot); - - // Give the listener thread a moment to bind - std::thread::sleep(std::time::Duration::from_millis(50)); - - let (pipe_r, pipe_w) = pipe(); - - // Send the pipe read end to the drain listener - send_drain_fds(&chroot, &[pipe_r.as_raw_fd()]); - drop(pipe_r); // close our copy; listener has its own - - // Write data — the listener should drain it (to stderr in production, - // but we just verify the pipe doesn't block/hang) - let mut writer = File::from(pipe_w); - for _ in 0..100 { - writer.write_all(b"log line\n").unwrap(); - } - drop(writer); - - // Give the drain thread time to process - std::thread::sleep(std::time::Duration::from_millis(100)); - // If we get here without hanging, the test passes. - } - - #[test] - fn test_send_drain_fds_no_socket_does_not_panic() { - // When no drain socket exists, send_drain_fds should silently return - let dir = test_dir(); - let (pipe_r, _pipe_w) = pipe(); - send_drain_fds(&dir, &[pipe_r.as_raw_fd()]); - // No panic, no error — best-effort - } -} diff --git a/sdk/package/lib/backup/Backups.ts b/sdk/package/lib/backup/Backups.ts index 335c8482f..158ca1037 100644 --- a/sdk/package/lib/backup/Backups.ts +++ b/sdk/package/lib/backup/Backups.ts @@ -220,6 +220,10 @@ export class Backups implements InitScript { async (sub) => { console.log('[pg-dump] mounting backup target') await mountBackupTarget(sub.rootfs) + await sub.exec(['touch', dumpFile], { user: 'root' }) + await sub.exec(['chown', 'postgres:postgres', dumpFile], { + user: 'root', + }) await startPg(sub, 'pg-dump') console.log('[pg-dump] dumping database') await sub.execFail( @@ -244,6 +248,10 @@ export class Backups implements InitScript { 'pg-restore', async (sub) => { await mountBackupTarget(sub.rootfs) + await sub.execFail( + ['chown', '-R', 'postgres:postgres', pgMountpoint], + { user: 'root' }, + ) await sub.execFail( ['initdb', '-D', pgdata, '-U', user, ...initdbArgs], { user: 'postgres' }, @@ -260,6 +268,7 @@ export class Backups implements InitScript { '-d', database, '--no-owner', + '--no-privileges', dumpFile, ], { user: 'postgres' }, From 2aa910a3e8ef866422371a8396cfb130a5a86256 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 23 Mar 2026 01:14:49 -0600 Subject: [PATCH 49/53] fix: replace stdio chown with prctl(PR_SET_DUMPABLE) and pipe-wrap After setuid, the kernel clears the dumpable flag, making /proc/self/ entries owned by root. This broke open("/dev/stderr") for non-root users inside subcontainers. The previous fix (chowning /proc/self/fd/*) was dangerous because it chowned whatever file the FD pointed to (could be the journal socket). The proper fix is prctl(PR_SET_DUMPABLE, 1) after setuid, which restores /proc/self/ ownership to the current uid. Additionally, adds a `pipe-wrap` subcommand that wraps a child process with piped stdout/stderr, relaying to the original FDs. This ensures all descendants inherit pipes (which support re-opening via /proc/self/fd/N) even when the outermost FDs are journal sockets. container-runtime.service now uses this wrapper. With pipe-wrap guaranteeing pipe-based FDs, the exec and launch non-TTY paths no longer need their own pipe+relay threads, eliminating the bug where exec would hang when a child daemonized (e.g. pg_ctl start). --- container-runtime/container-runtime.service | 2 +- core/src/service/effects/mod.rs | 4 + core/src/service/effects/subcontainer/sync.rs | 107 +++++++++++++++--- 3 files changed, 98 insertions(+), 15 deletions(-) diff --git a/container-runtime/container-runtime.service b/container-runtime/container-runtime.service index f04150969..e94753327 100644 --- a/container-runtime/container-runtime.service +++ b/container-runtime/container-runtime.service @@ -5,7 +5,7 @@ OnFailure=container-runtime-failure.service [Service] Type=simple Environment=RUST_LOG=startos=debug -ExecStart=/usr/bin/node --experimental-detect-module --trace-warnings /usr/lib/startos/init/index.js +ExecStart=/usr/bin/start-container pipe-wrap /usr/bin/node --experimental-detect-module --trace-warnings /usr/lib/startos/init/index.js Restart=no [Install] diff --git a/core/src/service/effects/mod.rs b/core/src/service/effects/mod.rs index 73d06467f..867865046 100644 --- a/core/src/service/effects/mod.rs +++ b/core/src/service/effects/mod.rs @@ -125,6 +125,10 @@ pub fn handler() -> ParentHandler { .with_call_remote::(), ), ) + .subcommand( + "pipe-wrap", + from_fn_blocking(subcontainer::pipe_wrap).no_display(), + ) // net .subcommand("bind", from_fn_async(net::bind::bind).no_cli()) .subcommand( diff --git a/core/src/service/effects/subcontainer/sync.rs b/core/src/service/effects/subcontainer/sync.rs index e1205a1a1..e6004e71c 100644 --- a/core/src/service/effects/subcontainer/sync.rs +++ b/core/src/service/effects/subcontainer/sync.rs @@ -487,28 +487,14 @@ pub fn launch( } cmd.arg(&chroot); cmd.args(&command); - cmd.stdin(Stdio::piped()); - cmd.stdout(Stdio::piped()); - cmd.stderr(Stdio::piped()); let mut child = cmd .spawn() .map_err(color_eyre::eyre::Report::msg) .with_ctx(|_| (ErrorKind::Filesystem, "spawning child process"))?; send_pid.send(child.id() as i32).unwrap_or_default(); - stdin_send - .send(Box::new(child.stdin.take().unwrap())) - .unwrap_or_default(); - stdout_send - .send(Box::new(child.stdout.take().unwrap())) - .unwrap_or_default(); - stderr_send - .send(Box::new(child.stderr.take().unwrap())) - .unwrap_or_default(); let exit = child .wait() .with_ctx(|_| (ErrorKind::Filesystem, "waiting on child process"))?; - stdout_thread.join().unwrap(); - stderr_thread.map(|t| t.join().unwrap()); if let Some(code) = exit.code() { nix::mount::umount(&chroot.join("proc")) .with_ctx(|_| (ErrorKind::Filesystem, "umount procfs"))?; @@ -767,3 +753,96 @@ pub fn exec( pub fn exec_command(_: ContainerCliContext, params: ExecParams) -> Result<(), Error> { params.exec() } + +/// Wrap a child process so that its stdout/stderr are always pipes, even when +/// the wrapper's own FDs are sockets (e.g. systemd journal). This lets +/// descendants `open("/dev/stderr")` via `/proc/self/fd/2` without ENXIO. +pub fn pipe_wrap( + _: ContainerCliContext, + PipeWrapParams { command }: PipeWrapParams, +) -> Result<(), Error> { + use std::os::fd::AsRawFd; + + let Some(([program], args)) = command.split_at_checked(1) else { + return Err(Error::new( + eyre!("pipe-wrap: command cannot be empty"), + ErrorKind::InvalidRequest, + )); + }; + + let mut cmd = StdCommand::new(program); + cmd.args(args); + cmd.stdout(Stdio::piped()); + cmd.stderr(Stdio::piped()); + + let mut child = cmd + .spawn() + .with_ctx(|_| (ErrorKind::Filesystem, "pipe-wrap: spawning child process"))?; + + let child_stdout = child.stdout.take().unwrap(); + let child_stderr = child.stderr.take().unwrap(); + + let orig_stdout_fd = std::io::stdout().as_raw_fd(); + let orig_stderr_fd = std::io::stderr().as_raw_fd(); + + // Relay child stdout → original stdout (which may be a socket) + std::thread::spawn(move || { + let mut reader = child_stdout; + let mut buf = [0u8; 8192]; + loop { + match Read::read(&mut reader, &mut buf) { + Ok(0) | Err(_) => break, + Ok(n) => { + let _ = nix::unistd::write( + unsafe { std::os::fd::BorrowedFd::borrow_raw(orig_stdout_fd) }, + &buf[..n], + ); + } + } + } + }); + + // Relay child stderr → original stderr + std::thread::spawn(move || { + let mut reader = child_stderr; + let mut buf = [0u8; 8192]; + loop { + match Read::read(&mut reader, &mut buf) { + Ok(0) | Err(_) => break, + Ok(n) => { + let _ = nix::unistd::write( + unsafe { std::os::fd::BorrowedFd::borrow_raw(orig_stderr_fd) }, + &buf[..n], + ); + } + } + } + }); + + // Forward signals to the child + let child_pid = child.id() as i32; + let mut sig = signal_hook::iterator::Signals::new(FWD_SIGNALS)?; + std::thread::spawn(move || { + for sig in sig.forever() { + match nix::sys::signal::kill( + Pid::from_raw(child_pid), + Some(nix::sys::signal::Signal::try_from(sig).unwrap()), + ) { + Err(Errno::ESRCH) => break, + _ => {} + } + } + }); + + let status = child + .wait() + .with_ctx(|_| (ErrorKind::Filesystem, "pipe-wrap: waiting on child"))?; + std::process::exit(status.code().unwrap_or(1)) +} + +#[derive(Debug, Clone, Serialize, Deserialize, Parser)] +#[group(skip)] +pub struct PipeWrapParams { + #[arg(trailing_var_arg = true, help = "help.arg.command-to-execute")] + command: Vec, +} From f60a1a9ed080db90e7deef521c8a51fb2e8796c4 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 23 Mar 2026 01:15:54 -0600 Subject: [PATCH 50/53] fix: set backup progress complete atomically with status revert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move BackupProgress { complete: true } into the same db.mutate() as the DesiredStatus revert in the backup transition. Previously these were separate mutations—the status would revert to Running before progress showed complete, causing a visible gap in the UI. --- core/src/backup/backup_bulk.rs | 16 ---------------- core/src/service/transition/backup.rs | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/core/src/backup/backup_bulk.rs b/core/src/backup/backup_bulk.rs index 79584c669..9e020240d 100644 --- a/core/src/backup/backup_bulk.rs +++ b/core/src/backup/backup_bulk.rs @@ -278,22 +278,6 @@ async fn perform_backup( timestamp: Utc::now(), }, ); - - ctx.db - .mutate(|db| { - if let Some(progress) = db - .as_public_mut() - .as_server_info_mut() - .as_status_info_mut() - .as_backup_progress_mut() - .transpose_mut() - { - progress.insert(&id, &BackupProgress { complete: true })?; - } - Ok(()) - }) - .await - .result?; } backup_report.insert( id.clone(), diff --git a/core/src/service/transition/backup.rs b/core/src/service/transition/backup.rs index 089d9f127..39e1a13e4 100644 --- a/core/src/service/transition/backup.rs +++ b/core/src/service/transition/backup.rs @@ -4,6 +4,7 @@ use futures::future::BoxFuture; use futures::{FutureExt, TryFutureExt}; use rpc_toolkit::yajrc::RpcError; +use crate::db::model::public::BackupProgress; use crate::disk::mount::filesystem::ReadWrite; use crate::prelude::*; use crate::rpc_continuations::Guid; @@ -29,6 +30,7 @@ impl ServiceActorSeed { ErrorKind::Cancelled, )) }; + let backup_succeeded = res.is_ok(); let id = &self.id; self.ctx .db @@ -49,7 +51,19 @@ impl ServiceActorSeed { } => DesiredStatus::Stopped, x => x, }) - }) + })?; + if backup_succeeded { + if let Some(progress) = db + .as_public_mut() + .as_server_info_mut() + .as_status_info_mut() + .as_backup_progress_mut() + .transpose_mut() + { + progress.insert(id, &BackupProgress { complete: true })?; + } + } + Ok(()) }) .await .result?; From 3d45234aae0bec08d53d7d06882db3b491ade64c Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Mon, 23 Mar 2026 08:58:37 -0600 Subject: [PATCH 51/53] fix password input for backups and add adjective noun randomizer --- .../src/app/pages/password.page.ts | 30 +- .../src/app/services/mock-api.service.ts | 10 +- .../shared/src/components/prompt.component.ts | 39 +- web/projects/shared/src/public-api.ts | 2 + web/projects/shared/src/util/hostname.ts | 13 +- .../shared/src/util/random-server-name.ts | 16 + .../shared/src/util/server-name-validator.ts | 26 + .../shared/src/util/server-name-words.ts | 8948 +++++++++++++++++ .../routes/general/server-name.dialog.ts | 44 +- .../ui/src/app/services/api/api.fixures.ts | 56 +- .../ui/src/app/services/api/mock-patch.ts | 2 +- 11 files changed, 9115 insertions(+), 71 deletions(-) create mode 100644 web/projects/shared/src/util/random-server-name.ts create mode 100644 web/projects/shared/src/util/server-name-validator.ts create mode 100644 web/projects/shared/src/util/server-name-words.ts diff --git a/web/projects/setup-wizard/src/app/pages/password.page.ts b/web/projects/setup-wizard/src/app/pages/password.page.ts index d3a22e2f7..d4fd63c1e 100644 --- a/web/projects/setup-wizard/src/app/pages/password.page.ts +++ b/web/projects/setup-wizard/src/app/pages/password.page.ts @@ -7,7 +7,13 @@ import { Validators, } from '@angular/forms' import { Router } from '@angular/router' -import { ErrorService, i18nPipe, normalizeHostname } from '@start9labs/shared' +import { + ErrorService, + i18nPipe, + normalizeHostname, + randomServerName, + serverNameValidator, +} from '@start9labs/shared' import { TuiAutoFocus, TuiMapperPipe, TuiValidator } from '@taiga-ui/cdk' import { TuiButton, @@ -42,10 +48,17 @@ import { StateService } from '../services/state.service' @if (isFresh) { - + + - @if (form.controls.name.value?.trim()) { + @if (form.controls.name.value?.trim() && !form.controls.name.errors) { } } @@ -127,6 +140,8 @@ import { StateService } from '../services/state.service' minlength: 'Must be 12 characters or greater', maxlength: 'Must be 64 character or less', match: 'Passwords do not match', + hostnameMinLength: 'Hostname must be at least 4 characters', + hostnameMaxLength: 'Hostname must be 63 characters or less', }), ], }) @@ -147,7 +162,10 @@ export default class PasswordPage { Validators.maxLength(64), ]), confirm: new FormControl(''), - name: new FormControl('', this.isFresh ? [Validators.required] : []), + name: new FormControl( + this.isFresh ? randomServerName() : '', + this.isFresh ? [Validators.required, serverNameValidator] : [], + ), }) readonly validator = (value: string) => (control: AbstractControl) => @@ -155,6 +173,10 @@ export default class PasswordPage { ? null : { match: this.i18n.transform('Passwords do not match') } + randomizeName() { + this.form.controls.name.setValue(randomServerName()) + } + get derivedHostname(): string { return normalizeHostname(this.form.controls.name.value || '') } diff --git a/web/projects/setup-wizard/src/app/services/mock-api.service.ts b/web/projects/setup-wizard/src/app/services/mock-api.service.ts index d073324d1..ead52298e 100644 --- a/web/projects/setup-wizard/src/app/services/mock-api.service.ts +++ b/web/projects/setup-wizard/src/app/services/mock-api.service.ts @@ -10,8 +10,8 @@ import { import { T } from '@start9labs/start-sdk' import * as jose from 'node-jose' import { interval, map, Observable } from 'rxjs' -import { ApiService } from './api.service' import { InstallOsParams, InstallOsRes } from '../types' +import { ApiService } from './api.service' @Injectable({ providedIn: 'root', @@ -127,7 +127,7 @@ export class MockApiService extends ApiService { return { '9876-5432-1234-5678': { hostname: 'adjective-noun', - version: '0.3.6', + version: '0.4.0', timestamp: new Date().toISOString(), passwordHash: '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', @@ -135,7 +135,7 @@ export class MockApiService extends ApiService { }, '9876-5432-1234-5671': { hostname: 'adjective-noun', - version: '0.3.6', + version: '0.4.0', timestamp: new Date().toISOString(), passwordHash: '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', @@ -299,7 +299,7 @@ const MOCK_DISKS: DiskInfo[] = [ startOs: { 'small-server-id': { hostname: 'small-server', - version: '0.3.6', + version: '0.4.0', timestamp: new Date().toISOString(), passwordHash: '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', @@ -348,7 +348,7 @@ const MOCK_DISKS: DiskInfo[] = [ startOs: { '1234-5678-9876-5432': { hostname: 'existing-server', - version: '0.3.6', + version: '0.4.0', timestamp: new Date().toISOString(), passwordHash: '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', diff --git a/web/projects/shared/src/components/prompt.component.ts b/web/projects/shared/src/components/prompt.component.ts index b266bcfa0..c55f5da3f 100644 --- a/web/projects/shared/src/components/prompt.component.ts +++ b/web/projects/shared/src/components/prompt.component.ts @@ -1,7 +1,8 @@ import { ChangeDetectionStrategy, Component } from '@angular/core' import { FormsModule } from '@angular/forms' import { TuiAutoFocus } from '@taiga-ui/cdk' -import { TuiButton, TuiDialogContext, TuiInput } from '@taiga-ui/core' +import { TuiButton, TuiDialogContext, TuiIcon, TuiInput } from '@taiga-ui/core' +import { TuiPassword } from '@taiga-ui/kit' import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus' import { i18nPipe } from '../i18n/i18n.pipe' import { i18nKey } from '../i18n/i18n.providers' @@ -27,22 +28,12 @@ import { i18nKey } from '../i18n/i18n.providers' tuiAutoFocus [ngModelOptions]="{ standalone: true }" [(ngModel)]="value" - [class.masked]="options.useMask && masked && value" [placeholder]="options.placeholder || ''" + [type]="options.useMask ? 'password' : 'text'" + [autocomplete]="options.useMask ? 'off' : ''" /> @if (options.useMask) { - + } @if (error) { @@ -71,24 +62,22 @@ import { i18nKey } from '../i18n/i18n.providers' .error { color: var(--tui-status-negative); } - - .button { - pointer-events: auto; - margin-left: 0.25rem; - } - - .masked { - -webkit-text-security: disc; - } `, - imports: [FormsModule, TuiButton, TuiInput, TuiAutoFocus, i18nPipe], + imports: [ + FormsModule, + TuiButton, + TuiIcon, + TuiInput, + TuiPassword, + TuiAutoFocus, + i18nPipe, + ], changeDetection: ChangeDetectionStrategy.OnPush, }) export class PromptModal { private readonly context = injectContext>() - masked = this.options.useMask value = this.options.initialValue || '' error = '' diff --git a/web/projects/shared/src/public-api.ts b/web/projects/shared/src/public-api.ts index 115c5c593..f6e506eed 100644 --- a/web/projects/shared/src/public-api.ts +++ b/web/projects/shared/src/public-api.ts @@ -57,3 +57,5 @@ export * from './util/unused' export * from './util/keyboards' export * from './util/languages' export * from './util/hostname' +export * from './util/random-server-name' +export * from './util/server-name-validator' diff --git a/web/projects/shared/src/util/hostname.ts b/web/projects/shared/src/util/hostname.ts index cdb190991..e8487225d 100644 --- a/web/projects/shared/src/util/hostname.ts +++ b/web/projects/shared/src/util/hostname.ts @@ -1,8 +1,8 @@ /** * TS port of the Rust `normalize()` function from core/src/hostname.rs. - * Converts a free-text name into a valid hostname. + * Strips non-alphanumeric characters and produces a raw hostname string. */ -export function normalizeHostname(name: string): string { +export function normalizeHostnameRaw(name: string): string { let prevWasDash = true let normalized = '' @@ -20,5 +20,12 @@ export function normalizeHostname(name: string): string { normalized = normalized.slice(0, -1) } - return normalized || 'start9' + return normalized +} + +/** + * Converts a free-text name into a valid hostname, with 'start9' fallback. + */ +export function normalizeHostname(name: string): string { + return normalizeHostnameRaw(name) || 'start9' } diff --git a/web/projects/shared/src/util/random-server-name.ts b/web/projects/shared/src/util/random-server-name.ts new file mode 100644 index 000000000..00c5300f2 --- /dev/null +++ b/web/projects/shared/src/util/random-server-name.ts @@ -0,0 +1,16 @@ +import { ADJECTIVES, NOUNS } from './server-name-words' + +/** + * Generates a random server name in "Adjective Noun" format. + * Uses the same word lists as the Rust backend (core/src/assets/). + */ +export function randomServerName(): string { + const adj = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)]! + const noun = NOUNS[Math.floor(Math.random() * NOUNS.length)]! + + return `${capitalize(adj)} ${capitalize(noun)}` +} + +function capitalize(word: string): string { + return word.charAt(0).toUpperCase() + word.slice(1) +} diff --git a/web/projects/shared/src/util/server-name-validator.ts b/web/projects/shared/src/util/server-name-validator.ts new file mode 100644 index 000000000..a8b3ed350 --- /dev/null +++ b/web/projects/shared/src/util/server-name-validator.ts @@ -0,0 +1,26 @@ +import { AbstractControl, ValidationErrors } from '@angular/forms' +import { normalizeHostnameRaw } from './hostname' + +// Matches backend normalize() threshold (core/src/hostname.rs:109) +const HOSTNAME_MIN_LENGTH = 4 +// DNS label limit +const HOSTNAME_MAX_LENGTH = 63 + +export function serverNameValidator( + control: AbstractControl, +): ValidationErrors | null { + const name = (control.value || '').trim() + if (!name) return null + + const hostname = normalizeHostnameRaw(name) + + if (hostname.length < HOSTNAME_MIN_LENGTH) { + return { hostnameMinLength: true } + } + + if (hostname.length > HOSTNAME_MAX_LENGTH) { + return { hostnameMaxLength: true } + } + + return null +} diff --git a/web/projects/shared/src/util/server-name-words.ts b/web/projects/shared/src/util/server-name-words.ts new file mode 100644 index 000000000..dbb807603 --- /dev/null +++ b/web/projects/shared/src/util/server-name-words.ts @@ -0,0 +1,8948 @@ +// Auto-generated from core/src/assets/{adjectives,nouns}.txt +// prettier-ignore +export const ADJECTIVES = [ + 'ominous', + 'sturdy', + 'angelic', + 'frontal', + 'legal', + 'murky', + 'rougher', + 'formal', + 'local', + 'bold', + 'grouchy', + 'grazing', + 'bumpy', + 'wonky', + 'boxed', + 'factual', + 'sunny', + 'trim', + 'selfish', + 'humble', + 'plastic', + 'broke', + 'shorter', + 'rustic', + 'brittle', + 'narrow', + 'astute', + 'icky', + 'sullen', + 'bemused', + 'creative', + 'snowy', + 'sane', + 'sedate', + 'deviant', + 'icy', + 'spoiled', + 'blond', + 'concave', + 'cyan', + 'lucky', + 'lively', + 'risky', + 'wounded', + 'greater', + 'limber', + 'social', + 'glued', + 'painful', + 'warm', + 'nutty', + 'amused', + 'carried', + 'amateur', + 'meager', + 'working', + 'faded', + 'stark', + 'reborn', + 'darkened', + 'entire', + 'charred', + 'speedy', + 'clear', + 'impish', + 'ageless', + 'prewar', + 'correct', + 'molten', + 'admired', + 'uneasy', + 'higher', + 'tragic', + 'inane', + 'magenta', + 'urban', + 'nearby', + 'grouped', + 'noisy', + 'rural', + 'fetid', + 'waxed', + 'dandy', + 'cocky', + 'aqua', + 'dingy', + 'unbent', + 'quiet', + 'mellow', + 'unvalued', + 'itchy', + 'clunky', + 'snug', + 'opaque', + 'bulky', + 'smug', + 'helpful', + 'velvet', + 'violet', + 'valid', + 'wobbly', + 'dodgy', + 'rare', + 'cocoa', + 'selfless', + 'complex', + 'simple', + 'prim', + 'blank', + 'obsolete', + 'surplus', + 'funky', + 'chubby', + 'daring', + 'spongy', + 'tinted', + 'prepaid', + 'geeky', + 'unsure', + 'broken', + 'wimpy', + 'monthly', + 'brown', + 'erased', + 'freaky', + 'decent', + 'rimless', + 'cordless', + 'tainted', + 'huffy', + 'yawning', + 'toxic', + 'puffy', + 'inner', + 'smart', + 'lesser', + 'mute', + 'mighty', + 'deluxe', + 'thatch', + 'frosty', + 'darkish', + 'fun', + 'annoying', + 'swollen', + 'loco', + 'magic', + 'generic', + 'tan', + 'trendy', + 'blind', + 'worried', + 'stray', + 'pungent', + 'fluid', + 'mixed', + 'ruby', + 'rabid', + 'silky', + 'regular', + 'winter', + 'sour', + 'sleepy', + 'frail', + 'dicey', + 'heavy', + 'rude', + 'asleep', + 'loony', + 'singing', + 'exterior', + 'bendy', + 'feeble', + 'intact', + 'robust', + 'foamy', + 'pale', + 'crazed', + 'sloping', + 'soaked', + 'next', + 'thorny', + 'voting', + 'squeaky', + 'pregame', + 'dismal', + 'teak', + 'rumbling', + 'furry', + 'hazel', + 'quaint', + 'older', + 'custard', + 'golden', + 'paltry', + 'phony', + 'smooth', + 'trivial', + 'happier', + 'unboxed', + 'chalky', + 'learned', + 'younger', + 'calm', + 'jagged', + 'still', + 'round', + 'final', + 'unhappy', + 'jumbo', + 'obedient', + 'germy', + 'mangy', + 'pickled', + 'untamed', + 'puny', + 'pink', + 'mild', + 'mini', + 'able', + 'related', + 'auburn', + 'giddy', + 'tapered', + 'flabby', + 'awake', + 'artsy', + 'dull', + 'virtual', + 'dry', + 'useless', + 'winking', + 'nerdy', + 'drastic', + 'dimpled', + 'slick', + 'purple', + 'jolly', + 'maple', + 'humorous', + 'swank', + 'ready', + 'level', + 'shrill', + 'amusing', + 'grim', + 'crabby', + 'canned', + 'anxious', + 'refried', + 'undying', + 'revised', + 'spicy', + 'refined', + 'aquatic', + 'foggy', + 'chosen', + 'grey', + 'bespoke', + 'flavored', + 'baggy', + 'foul', + 'shocked', + 'unlucky', + 'yapping', + 'insecure', + 'daft', + 'sleazy', + 'unused', + 'short', + 'snarky', + 'tweed', + 'rosy', + 'brief', + 'welcome', + 'buffed', + 'enamel', + 'inept', + 'abrupt', + 'taboo', + 'hungry', + 'audible', + 'bitter', + 'untidy', + 'stale', + 'strong', + 'moldy', + 'brass', + 'crisp', + 'temp', + 'acidic', + 'top', + 'old', + 'limited', + 'neon', + 'cushy', + 'angled', + 'potent', + 'rotten', + 'snappy', + 'floppy', + 'good', + 'darned', + 'somber', + 'stunned', + 'unloved', + 'endless', + 'wavy', + 'louder', + 'musty', + 'distant', + 'savage', + 'devout', + 'feisty', + 'rogue', + 'uneven', + 'excess', + 'main', + 'crimson', + 'illicit', + 'normal', + 'faux', + 'quick', + 'trite', + 'guilty', + 'kosher', + 'beloved', + 'wooden', + 'indigo', + 'gentle', + 'subtle', + 'finer', + 'stained', + 'wanted', + 'informal', + 'cute', + 'cedar', + 'returned', + 'square', + 'shady', + 'prissy', + 'bronze', + 'meaty', + 'taller', + 'vegan', + 'flying', + 'cloudy', + 'vague', + 'snazzy', + 'twisty', + 'primary', + 'timid', + 'liquid', + 'left', + 'nifty', + 'red', + 'alright', + 'smoky', + 'western', + 'okay', + 'fine', + 'armored', + 'rinsing', + 'denim', + 'glib', + 'routine', + 'silver', + 'harsh', + 'near', + 'useful', + 'preachy', + 'tedious', + 'arctic', + 'bluish', + 'primal', + 'medical', + 'sore', + 'buff', + 'patchy', + 'chief', + 'swell', + 'adept', + 'ideal', + 'yummy', + 'gutsy', + 'key', + 'mocha', + 'harmful', + 'loyal', + 'oblong', + 'dense', + 'great', + 'lousy', + 'emerald', + 'large', + 'magnum', + 'dancing', + 'chewy', + 'ashamed', + 'teal', + 'secular', + 'curly', + 'fertile', + 'furtive', + 'ruined', + 'spry', + 'pliable', + 'beige', + 'bony', + 'frantic', + 'wary', + 'muscled', + 'past', + 'jumpy', + 'legit', + 'glossy', + 'fishy', + 'corny', + 'small', + 'crying', + 'beefy', + 'pompous', + 'tough', + 'proper', + 'nimble', + 'vital', + 'foolish', + 'dainty', + 'rough', + 'herbal', + 'brainy', + 'afraid', + 'frilly', + 'hectic', + 'frigid', + 'bogus', + 'skilled', + 'tasty', + 'private', + 'slobbery', + 'plump', + 'shaved', + 'fatty', + 'initial', + 'zippy', + 'oldest', + 'bad', + 'nasty', + 'lame', + 'careless', + 'flaxen', + 'moonlit', + 'spare', + 'candied', + 'crafty', + 'hollow', + 'eager', + 'pointy', + 'caustic', + 'wronged', + 'dinky', + 'manmade', + 'niche', + 'fair', + 'varied', + 'melting', + 'blazing', + 'crass', + 'renewed', + 'waxy', + 'bald', + 'big', + 'passive', + 'slimy', + 'iced', + 'ultimate', + 'hairy', + 'dyed', + 'elusive', + 'sunken', + 'emphatic', + 'yeasty', + 'overt', + 'frugal', + 'ditzy', + 'remote', + 'clumsy', + 'diabetic', + 'ladylike', + 'swampy', + 'aging', + 'fur', + 'lined', + 'bossy', + 'dorky', + 'mobile', + 'crushed', + 'slate', + 'immense', + 'easiest', + 'pointed', + 'rented', + 'minty', + 'expert', + 'new', + 'maroon', + 'elfish', + 'zany', + 'drafty', + 'ceramic', + 'felt', + 'hideous', + 'marine', + 'elastic', + 'oozy', + 'novel', + 'hasty', + 'weary', + 'stuffy', + 'capable', + 'inert', + 'default', + 'central', + 'sweaty', + 'sloped', + 'smoked', + 'creepy', + 'vexed', + 'bionic', + 'regal', + 'cranky', + 'steep', + 'open', + 'floral', + 'movable', + 'varsity', + 'docile', + 'basic', + 'coping', + 'meek', + 'loose', + 'fried', + 'plush', + 'fuzzy', + 'creaky', + 'white', + 'tubular', + 'angular', + 'edgy', + 'visible', + 'curvy', + 'neutral', + 'low', + 'woozy', + 'edible', + 'dill', + 'yucky', + 'camo', + 'hopeless', + 'polite', + 'smoggy', + 'wacky', + 'crude', + 'imposing', + 'west', + 'shaky', + 'rebel', + 'soft', + 'mythic', + 'sheer', + 'flat', + 'aft', + 'wriggly', + 'citric', + 'noble', + 'crazy', + 'blurry', + 'insane', + 'spooky', + 'touchy', + 'unique', + 'bare', + 'funny', + 'sincere', + 'eldest', + 'unusual', + 'granite', + 'prime', + 'sooty', + 'engaged', + 'awful', + 'tangible', + 'manual', + 'weaker', + 'lukewarm', + 'junky', + 'amber', + 'gothic', + 'light', + 'scabby', + 'unkind', + 'empty', + 'porous', + 'subdued', + 'frizzy', + 'yellow', + 'tall', + 'foreign', + 'anemic', + 'lean', + 'cuddly', + 'wrong', + 'upbeat', + 'greedy', + 'stout', + 'dotted', + 'alive', + 'profound', + 'frozen', + 'lavish', + 'wax', + 'onyx', + 'milky', + 'veteran', + 'thin', + 'classic', + 'personal', + 'taxable', + 'lasting', + 'random', + 'valiant', + 'pulpy', + 'stiff', + 'dirty', + 'retired', + 'secret', + 'lacy', + 'online', + 'royal', + 'wild', + 'found', + 'nervous', + 'viable', + 'dusty', + 'peachy', + 'sudsy', + 'moody', + 'askew', + 'sad', + 'little', + 'convex', + 'grubby', + 'broad', + 'employed', + 'glass', + 'muscular', + 'avian', + 'direct', + 'goofy', + 'absent', + 'boiling', + 'loving', + 'gaudy', + 'micro', + 'muggy', + 'happy', + 'nearest', + 'strange', + 'growing', + 'ashy', + 'brisk', + 'sporty', + 'blunt', + 'stoic', + 'high', + 'mundane', + 'newborn', + 'longer', + 'needy', + 'feral', + 'plain', + 'front', + 'mature', + 'lucid', + 'washed', + 'husky', + 'eerie', + 'unseen', + 'weepy', + 'strict', + 'real', + 'hyper', + 'orange', + 'raw', + 'stormy', + 'foxy', + 'latex', + 'dang', + 'tired', + 'fragile', + 'tactful', + 'active', + 'squishy', + 'wealthy', + 'portly', + 'magical', + 'curved', + 'fasting', + 'worn', + 'silent', + 'wiry', + 'replica', + 'tame', + 'backlit', + 'fragrant', + 'nice', + 'adapted', + 'wet', + 'first', + 'whole', + 'unarmed', + 'suitable', + 'sober', + 'green', + 'oiled', + 'benign', + 'only', + 'erratic', + 'lonely', + 'balsa', + 'poor', + 'damp', + 'spiffy', + 'groggy', + 'losing', + 'black', + 'vast', + 'rusted', + 'leaky', + 'blocky', + 'futile', + 'decaf', + 'prompt', + 'ironic', + 'sulky', + 'giant', + 'folded', + 'tender', + 'mean', + 'powered', + 'tacky', + 'single', + 'hot', + 'moist', + 'lush', + 'slim', + 'ripe', + 'messy', + 'aloof', + 'blotchy', + 'shaggy', + 'billowy', + 'boring', + 'usual', + 'bloated', + 'cheap', + 'medium', + 'secure', + 'subpar', + 'holy', + 'trusty', + 'steel', + 'solid', + 'starchy', + 'worst', + 'better', + 'nosy', + 'tepid', + 'irate', + 'wispy', + 'bored', + 'sharper', + 'damn', + 'epic', + 'dreary', + 'neat', + 'dank', + 'crooked', + 'urgent', + 'stupid', + 'mousy', + 'filthy', + 'usable', + 'burly', + 'kooky', + 'tangled', + 'rusty', + 'illegal', + 'optimal', + 'sudden', + 'marble', + 'mint', + 'padded', + 'closed', + 'onerous', + 'lit', + 'uneaten', + 'bushy', + 'bootleg', + 'robotic', + 'scary', + 'petite', + 'late', + 'bent', + 'kind', + 'radiant', + 'ivory', + 'alpine', + 'joyous', + 'batty', + 'copper', + 'ample', + 'armed', + 'extra', + 'wise', + 'vintage', + 'butch', + 'sharp', + 'tied', + 'glum', + 'sticky', + 'free', + 'pure', + 'stinky', + 'super', + 'humid', + 'dark', + 'grimy', + 'senior', + 'sneaky', + 'wide', + 'detached', + 'twitchy', + 'brawny', + 'hefty', + 'tidy', + 'ancient', + 'thinner', + 'badass', + 'fancy', + 'barbed', + 'native', + 'fresh', + 'buggy', + 'exposed', + 'gummy', + 'pudgy', + 'chrome', + 'deaf', + 'busy', + 'bamboo', + 'amazing', + 'dear', + 'scenic', + 'knit', + 'fruity', + 'young', + 'demur', + 'sugary', + 'deep', + 'fantasy', + 'antique', + 'brunette', + 'vanilla', + 'leather', + 'undead', + 'torn', + 'extinct', + 'vivid', + 'serious', + 'lost', + 'amiable', + 'sassy', + 'poison', + 'slushy', + 'mossy', + 'hardy', + 'hard', + 'favored', + 'cheesy', + 'bizarre', + 'lead', + 'sacred', + 'married', + 'custom', + 'static', + 'idle', + 'pagan', + 'bland', + 'wrinkly', + 'safest', + 'odd', + 'breezy', + 'hybrid', + 'natural', + 'maimed', + 'rocky', + 'frosted', + 'fond', + 'salty', + 'skinny', + 'sage', + 'blue', + 'sizable', + 'spiral', + 'mammoth', + 'crunchy', + 'gifted', + 'turbo', + 'female', + 'live', + 'warming', + 'dire', + 'woody', + 'massive', + 'festive', + 'lax', + 'upright', + 'tight', + 'fat', + 'sloppy', + 'silly', + 'shoddy', + 'acrid', + 'angry', + 'gloomy', + 'onshore', + 'unfair', + 'rapid', + 'virgin', + 'fluffy', + 'eroded', + 'best', + 'warped', + 'gold', + 'steady', + 'slow', + 'swift', + 'postwar', + 'rich', + 'feudal', + 'whacky', + 'partial', + 'dreaded', + 'common', + 'elegant', + 'isolated', + 'thick', + 'homeless', + 'loud', + 'playful', + 'bright', + 'disco', + 'far', + 'jubilant', + 'woven', + 'dizzy', + 'joyful', + 'stuck', + 'weak', + 'fake', + 'dumb', + 'costly', + 'verdant', + 'soapy', + 'content', + 'unjust', + 'healthy', + 'agile', + 'superb', + 'elated', + 'catchy', + 'proud', + 'dreamy', + 'hunky', + 'mega', + 'chunky', + 'undated', + 'rotund', + 'rad', + 'drippy', + 'satin', + 'exotic', + 'drab', + 'surly', + 'slinky', + 'whiny', + 'early', + 'fleshy', + 'curled', + 'marbled', + 'mashed', + 'brave', + 'botched', + 'pastel', + 'rubber', + 'ebony', + 'frayed', + 'general', + 'dental', + 'groovy', + 'dazzling', + 'devious', + 'elite', + 'junior', + 'last', + 'tangy', + 'huge', + 'chic', + 'bonus', + 'eastern', + 'upscale', + 'shiny', + 'gross', + 'jaded', + 'perky', + 'average', + 'lumpy', + 'used', + 'skiing', + 'warmer', + 'nuclear', + 'upset', + 'awkward', + 'kinder', + 'watery', + 'utopian', + 'hissy', + 'ornate', + 'greasy', + 'long', + 'baroque', + 'worthy', + 'bovine', + 'weird', + 'chaotic', + 'lazy', + 'covert', + 'bottom', + 'modest', + 'obvious', + 'nomadic', + 'public', + 'patient', + 'handy', + 'posh', + 'antsy', + 'crucial', + 'popular', + 'current', + 'creamy', + 'caring', + 'similar', + 'sleek', + 'saggy', + 'extreme', + 'vain', + 'weedy', + 'fizzy', + 'mad', + 'tense', + 'comfy', + 'uptight', + 'vile', + 'macho', + 'glowing', + 'lurid', + 'durable', + 'cozy', + 'fabric', + 'fit', + 'male', + 'plaid', + 'boxy', + 'finicky', + 'fast', + 'stern', + 'napping', + 'glad', + 'fickle', + 'dynamic', + 'perfect', + 'burnt', + 'cool', + 'windy', + 'tardy', + 'thrifty', + 'defiant', + 'crispy', + 'bouncy', + 'juicy', + 'saffron', + 'just', + 'wool', + 'crummy', + 'oaky', + 'soggy', + 'tiny', + 'supreme', + 'tested', + 'azure', + 'soupy', + 'coarse', + 'wicked', + 'thirsty', + 'tart', + 'tapping', + 'modern', + 'leafy', + 'stony', + 'singed', + 'minor', + 'painted', + 'logical', + 'former', + 'deeper', + 'sterile', + 'tin', + 'pleasant', + 'firm', + 'kindly', + 'coveted', + 'eternal', + 'pushy', + 'runny', + 'austere', + 'stocky', + 'rigid', + 'flashy', + 'tricky', + 'upstate', + 'scruffy', + 'testy', + 'absurd', + 'cold', + 'lilac', + 'pebbly', + 'oval', + 'creased', + 'clever', + 'viral', + 'hidden', + 'modular', + 'mushy', + 'recent', + 'dried', + 'chaste', + 'bubbly', + 'earthy', + 'jealous', + 'shabby', + 'copied', + 'iffy', + 'official', + 'core', + 'alert', + 'crusty', + 'shy', + 'jovial', + 'safe', + 'shifty', + 'dusky', + 'roomy', + 'petty', + 'grumpy', + 'educated', + 'sandy', + 'numb', + 'vibrant', + 'armless', + 'retro', + 'starlit', + 'sly', + 'wood', + 'aged', + 'enraged', + 'flawed', + 'indoor', + 'fixed', + 'metal', + 'fussy', + 'muddy', + 'witty', + 'gray', + 'bleak', + 'honest', + 'grand', + 'full', + 'jelly', + 'shallow', + 'simpler', + 'cosmic', + 'scarlet', + 'musky', + 'donated', + 'heroic', + 'naive', + 'salted', + 'painless', + 'trained', + 'inky', + 'zesty', + 'scarce', + 'boiled', + 'rookie', + 'scented', + 'measly', + 'quirky', + 'exempt', + 'sweet', + 'pesky', + 'spotty', + 'easy', + 'sublime', + 'elderly', + 'faster', + 'clean', + 'daily', + 'wired', + 'bouncing', + 'organic', + 'gaunt', + 'swanky', + 'mouthy', + 'tipsy', + 'candid', + 'scared', + 'homely', + 'arcane', + 'weekly', + 'rowdy', + 'impure', + 'stable', + 'vapid', + 'buttery', + 'oily', + 'pretty', + 'unsafe', + 'gnarly', + 'limp', + 'more', +] + +// prettier-ignore +export const NOUNS = [ + 'scowls', + 'zest', + 'regime', + 'heist', + 'films', + 'bling', + 'lent', + 'hassle', + 'collar', + 'flock', + 'mountain', + 'river', + 'caveman', + 'row', + 'spyglass', + 'visions', + 'jelly', + 'cymbal', + 'pedestrian', + 'joke', + 'nets', + 'money', + 'songbird', + 'scuba', + 'toddy', + 'litter', + 'ginger', + 'gyms', + 'paws', + 'kits', + 'human', + 'mandolin', + 'molt', + 'lyric', + 'clot', + 'plural', + 'senator', + 'museums', + 'goose', + 'rams', + 'artwork', + 'reveler', + 'dweeb', + 'scale', + 'distress', + 'looms', + 'burial', + 'native', + 'trio', + 'spirits', + 'refuse', + 'worrier', + 'rave', + 'mercy', + 'prong', + 'plethora', + 'mojo', + 'captives', + 'edicts', + 'creamer', + 'grips', + 'devices', + 'hobo', + 'dips', + 'irony', + 'dominion', + 'kilo', + 'manicure', + 'sequel', + 'locust', + 'yew', + 'pills', + 'penalty', + 'veggie', + 'airbag', + 'charge', + 'lance', + 'safe', + 'regalia', + 'kindling', + 'gent', + 'cloud', + 'volley', + 'democrats', + 'marks', + 'flutes', + 'fracture', + 'crepe', + 'fork', + 'jails', + 'union', + 'seltzer', + 'bores', + 'coats', + 'motel', + 'fairies', + 'uncle', + 'garage', + 'expense', + 'role', + 'context', + 'form', + 'brush', + 'puma', + 'thief', + 'snare', + 'pixy', + 'pageant', + 'hedge', + 'colonies', + 'bishops', + 'vessel', + 'glimpses', + 'peanuts', + 'ordeal', + 'cakes', + 'miles', + 'dogmas', + 'slang', + 'pranks', + 'sibling', + 'laxative', + 'gnat', + 'dip', + 'fuel', + 'cone', + 'edit', + 'imprint', + 'musk', + 'derby', + 'crush', + 'ticks', + 'abstinence', + 'statues', + 'fidelity', + 'rein', + 'swans', + 'poodle', + 'cads', + 'skunks', + 'togas', + 'gutters', + 'comics', + 'apology', + 'lobbies', + 'bundle', + 'helpline', + 'cook', + 'hunter', + 'idol', + 'loader', + 'blow', + 'relative', + 'feminism', + 'sword', + 'rugs', + 'corner', + 'gumball', + 'sail', + 'caps', + 'rarity', + 'putt', + 'class', + 'squads', + 'tourist', + 'mourners', + 'goblets', + 'scooter', + 'shark', + 'tuition', + 'card', + 'wallet', + 'luge', + 'alcohol', + 'swing', + 'studio', + 'player', + 'convent', + 'jogging', + 'disc', + 'hide', + 'babes', + 'bridges', + 'switch', + 'thunder', + 'spearman', + 'bonuses', + 'daddy', + 'sorcery', + 'cookbook', + 'net', + 'selector', + 'pelican', + 'hubcap', + 'umps', + 'ticket', + 'blizzard', + 'escape', + 'phonics', + 'handball', + 'dupe', + 'ink', + 'prongs', + 'lamps', + 'rocks', + 'snap', + 'inlay', + 'hatbox', + 'quakes', + 'scalp', + 'spare', + 'canister', + 'echo', + 'award', + 'pitcher', + 'robots', + 'fringe', + 'dregs', + 'wines', + 'gust', + 'joey', + 'conduct', + 'gyration', + 'night', + 'cab', + 'bees', + 'entries', + 'bagel', + 'ivory', + 'squire', + 'hairdo', + 'energy', + 'talent', + 'agency', + 'elder', + 'bonfires', + 'bacon', + 'dues', + 'plantation', + 'joust', + 'charter', + 'occasion', + 'icing', + 'salad', + 'walk', + 'clamp', + 'diaper', + 'scull', + 'hosts', + 'spuds', + 'stall', + 'mines', + 'wives', + 'cortex', + 'heroes', + 'clasps', + 'lane', + 'paint', + 'snobs', + 'farms', + 'sweep', + 'tunnel', + 'cups', + 'bear', + 'fangs', + 'cruelty', + 'moans', + 'proof', + 'swats', + 'owners', + 'wasabi', + 'riots', + 'cheese', + 'photon', + 'militia', + 'gurus', + 'sparks', + 'chisel', + 'borough', + 'scream', + 'effort', + 'trifles', + 'edge', + 'metro', + 'rats', + 'mediums', + 'novice', + 'internet', + 'manhood', + 'petal', + 'spoilage', + 'bread', + 'oil', + 'curry', + 'sills', + 'bit', + 'festival', + 'scrooge', + 'quality', + 'escort', + 'dub', + 'dares', + 'slot', + 'bangs', + 'rite', + 'socket', + 'candle', + 'fairy', + 'harpy', + 'anthems', + 'damages', + 'hound', + 'leaf', + 'serf', + 'splice', + 'profit', + 'fingers', + 'gout', + 'flaxseed', + 'feast', + 'surprise', + 'trolls', + 'zodiacs', + 'scoundrel', + 'activists', + 'deity', + 'sloth', + 'bottles', + 'limo', + 'hamlet', + 'flash', + 'comet', + 'salon', + 'garbage', + 'entree', + 'picnics', + 'cursor', + 'fabrics', + 'kidney', + 'dancers', + 'pellet', + 'scopes', + 'gulp', + 'doggy', + 'porch', + 'lute', + 'junction', + 'chill', + 'ammo', + 'letters', + 'codes', + 'snake', + 'disease', + 'sympathy', + 'mishap', + 'sprains', + 'ripple', + 'crusaders', + 'baby', + 'facility', + 'courier', + 'finale', + 'writing', + 'fragrance', + 'fees', + 'mocker', + 'earwig', + 'tantrum', + 'hacking', + 'flatware', + 'vicinity', + 'minks', + 'pram', + 'session', + 'earful', + 'shunt', + 'grudge', + 'straw', + 'playtime', + 'girth', + 'straps', + 'exhaust', + 'pushover', + 'can', + 'bits', + 'metal', + 'chariot', + 'men', + 'terms', + 'trombone', + 'bias', + 'concepts', + 'quake', + 'purl', + 'insults', + 'tipper', + 'manger', + 'keyboard', + 'pope', + 'coeds', + 'lobes', + 'oafs', + 'reader', + 'views', + 'orders', + 'empress', + 'activist', + 'jungles', + 'severity', + 'brail', + 'doctrine', + 'tractor', + 'rodeo', + 'shelves', + 'rod', + 'toga', + 'lips', + 'bend', + 'sums', + 'darkrooms', + 'grunge', + 'bite', + 'carving', + 'gang', + 'heel', + 'rotors', + 'couples', + 'lanes', + 'dissenter', + 'groups', + 'balconies', + 'clods', + 'monogram', + 'beard', + 'genres', + 'backhoe', + 'plums', + 'alumni', + 'schedule', + 'taper', + 'whim', + 'riff', + 'stories', + 'peer', + 'chop', + 'statutes', + 'posers', + 'slacks', + 'burro', + 'urns', + 'adversary', + 'cage', + 'blocks', + 'figs', + 'acts', + 'well', + 'light', + 'reseller', + 'weight', + 'ratios', + 'heathen', + 'whisk', + 'plan', + 'babe', + 'prose', + 'puff', + 'jokers', + 'colonel', + 'puppet', + 'guise', + 'retainer', + 'subplot', + 'rodent', + 'underdog', + 'diva', + 'pugs', + 'glut', + 'fighter', + 'aprons', + 'dare', + 'clones', + 'gravy', + 'sender', + 'gate', + 'muff', + 'snowsuit', + 'devourer', + 'gallon', + 'affair', + 'oboe', + 'mirrors', + 'timothy', + 'ricotta', + 'spool', + 'pear', + 'locket', + 'fact', + 'village', + 'laptop', + 'mower', + 'hair', + 'brawls', + 'ankle', + 'dots', + 'hour', + 'grill', + 'chin', + 'recovery', + 'result', + 'helms', + 'stags', + 'starlet', + 'fallacy', + 'wisps', + 'flowers', + 'thrones', + 'bout', + 'farmland', + 'contacts', + 'trickery', + 'footwear', + 'cat', + 'briefs', + 'frill', + 'link', + 'pedal', + 'flyover', + 'path', + 'stews', + 'paradox', + 'reactor', + 'version', + 'push', + 'salts', + 'quilt', + 'output', + 'pikes', + 'affairs', + 'conscript', + 'lock', + 'landfill', + 'superman', + 'apache', + 'fraction', + 'pupils', + 'gloss', + 'wafer', + 'nurse', + 'air', + 'habitat', + 'repeater', + 'mars', + 'deals', + 'play', + 'fob', + 'mothball', + 'chefs', + 'victor', + 'bingo', + 'footsie', + 'passcode', + 'tragedy', + 'botanists', + 'tasks', + 'friar', + 'ramps', + 'glory', + 'stripe', + 'wolves', + 'muscle', + 'penguin', + 'upside', + 'factoid', + 'rubble', + 'pancreas', + 'festivals', + 'triumph', + 'refining', + 'fence', + 'threat', + 'antlers', + 'tint', + 'giant', + 'father', + 'flirts', + 'gear', + 'syrup', + 'pandas', + 'hurler', + 'theft', + 'daze', + 'haggler', + 'adhesive', + 'stretch', + 'removal', + 'harp', + 'isle', + 'gratuity', + 'fink', + 'families', + 'sandbank', + 'tapioca', + 'onus', + 'boats', + 'laces', + 'incense', + 'sizzle', + 'rain', + 'pith', + 'winter', + 'flakes', + 'glee', + 'smashup', + 'tides', + 'poles', + 'skeet', + 'petals', + 'reward', + 'pothole', + 'brig', + 'renderer', + 'fritter', + 'thistle', + 'gasoline', + 'lynx', + 'jury', + 'spout', + 'hoax', + 'roars', + 'stain', + 'razor', + 'power', + 'bio', + 'moments', + 'creel', + 'spud', + 'tears', + 'luster', + 'uptake', + 'domains', + 'balloon', + 'subs', + 'pueblo', + 'moan', + 'retiree', + 'ring', + 'wing', + 'symptom', + 'ceiling', + 'warranty', + 'strolls', + 'grimace', + 'trilogy', + 'tool', + 'images', + 'disco', + 'ump', + 'nirvana', + 'bet', + 'phantom', + 'hags', + 'axle', + 'serving', + 'plow', + 'reach', + 'gym', + 'pelt', + 'caves', + 'duet', + 'pouch', + 'homage', + 'senate', + 'roger', + 'solvent', + 'sardine', + 'boot', + 'elective', + 'hulks', + 'shelter', + 'gophers', + 'resource', + 'baboon', + 'flooding', + 'trend', + 'album', + 'beetle', + 'spindle', + 'coma', + 'flora', + 'scripts', + 'oils', + 'scar', + 'shimmy', + 'torso', + 'population', + 'sandworm', + 'malt', + 'honeybee', + 'pauper', + 'pears', + 'letdown', + 'tavern', + 'squall', + 'crane', + 'nooks', + 'lake', + 'shelving', + 'gulls', + 'naming', + 'cameras', + 'mesa', + 'character', + 'strobe', + 'number', + 'gore', + 'indexes', + 'heat', + 'cougar', + 'placard', + 'tribute', + 'murmurs', + 'junta', + 'cake', + 'ad', + 'reason', + 'diapers', + 'jellies', + 'squabble', + 'contours', + 'rogue', + 'stereo', + 'twerp', + 'slog', + 'swag', + 'duchess', + 'waif', + 'error', + 'customs', + 'curb', + 'crusts', + 'wounds', + 'gardens', + 'wrecker', + 'volcano', + 'bandanna', + 'feasts', + 'punishment', + 'needs', + 'sedation', + 'dance', + 'hinge', + 'handle', + 'advisor', + 'bargain', + 'flipper', + 'car', + 'toolbox', + 'stub', + 'barista', + 'lair', + 'almond', + 'panda', + 'courses', + 'cokes', + 'playlist', + 'domino', + 'pauses', + 'lox', + 'gaskets', + 'discovery', + 'welds', + 'fervor', + 'crypts', + 'vote', + 'ships', + 'fame', + 'volume', + 'audio', + 'fear', + 'browser', + 'hail', + 'streams', + 'nod', + 'punch', + 'novices', + 'breeches', + 'shrieks', + 'dribble', + 'brakes', + 'progeny', + 'softy', + 'baseball', + 'march', + 'hardhat', + 'rims', + 'meadow', + 'falls', + 'word', + 'gusts', + 'dude', + 'pip', + 'marmot', + 'magic', + 'velocity', + 'mitt', + 'outage', + 'relic', + 'chapter', + 'steaks', + 'pawns', + 'upheaval', + 'towns', + 'famine', + 'crashes', + 'chai', + 'squiggle', + 'headlock', + 'quiver', + 'clasp', + 'oath', + 'wiz', + 'malts', + 'vans', + 'gambling', + 'barbarian', + 'decibels', + 'handset', + 'naturist', + 'florist', + 'larks', + 'barges', + 'bonds', + 'bomber', + 'bowls', + 'robotics', + 'enemy', + 'ports', + 'steak', + 'polls', + 'randy', + 'omelet', + 'solids', + 'lodges', + 'pixel', + 'loads', + 'oyster', + 'crimps', + 'theist', + 'wails', + 'heroics', + 'genre', + 'herb', + 'pork', + 'reproach', + 'bevel', + 'seashore', + 'rematch', + 'lama', + 'adage', + 'tidbit', + 'innovation', + 'home', + 'twang', + 'vagrant', + 'pagan', + 'nudge', + 'hoops', + 'ribbon', + 'ancestry', + 'hacker', + 'disgrace', + 'jot', + 'olive', + 'trends', + 'lead', + 'seas', + 'fishhook', + 'sale', + 'costume', + 'sill', + 'tong', + 'nosh', + 'monument', + 'wings', + 'market', + 'sternum', + 'freeware', + 'roster', + 'luncheon', + 'bliss', + 'fire', + 'cube', + 'pizzas', + 'ears', + 'vegan', + 'belch', + 'brie', + 'pruning', + 'carts', + 'wad', + 'beavers', + 'hardener', + 'axles', + 'totem', + 'chain', + 'try', + 'vice', + 'ravine', + 'goblet', + 'bid', + 'spelt', + 'wit', + 'ghost', + 'chowder', + 'cries', + 'glimpse', + 'mystery', + 'curbs', + 'brake', + 'faults', + 'dealers', + 'turkey', + 'sanctuary', + 'eyelid', + 'tanks', + 'members', + 'mailbox', + 'yelps', + 'forge', + 'firs', + 'sight', + 'senators', + 'tenant', + 'province', + 'debts', + 'edges', + 'leg', + 'mailroom', + 'breed', + 'mildew', + 'treaty', + 'jays', + 'puffin', + 'duplex', + 'herring', + 'cardinal', + 'mole', + 'promoter', + 'woodland', + 'meatball', + 'shower', + 'yeti', + 'disk', + 'cartoons', + 'byte', + 'peaches', + 'mirth', + 'ode', + 'gift', + 'gallery', + 'cot', + 'ointment', + 'jogs', + 'bran', + 'vicar', + 'fats', + 'lids', + 'squeak', + 'band', + 'tick', + 'oracle', + 'hats', + 'van', + 'turmoil', + 'chums', + 'frown', + 'cysts', + 'dumpling', + 'vendors', + 'sorority', + 'junkies', + 'panic', + 'moods', + 'amputee', + 'vitality', + 'myths', + 'dusk', + 'wasps', + 'eggplant', + 'equation', + 'issues', + 'tummy', + 'focus', + 'gland', + 'hopes', + 'audience', + 'suction', + 'luck', + 'mummy', + 'smirk', + 'oaf', + 'splendor', + 'tutu', + 'pendant', + 'estrogen', + 'dummy', + 'rung', + 'pant', + 'makeup', + 'chemist', + 'journey', + 'boxer', + 'hood', + 'stripes', + 'marbling', + 'earphone', + 'theories', + 'walnuts', + 'eggshell', + 'loop', + 'vents', + 'platypus', + 'bob', + 'rider', + 'encore', + 'operas', + 'doodle', + 'ferry', + 'shim', + 'apricot', + 'prints', + 'stoops', + 'estimate', + 'snort', + 'rakes', + 'grains', + 'outpour', + 'petunia', + 'smack', + 'rubber', + 'force', + 'concept', + 'brisket', + 'atheist', + 'quota', + 'bundles', + 'chow', + 'furniture', + 'passes', + 'mast', + 'calcium', + 'chip', + 'jalapeno', + 'empire', + 'grout', + 'stools', + 'feet', + 'gosling', + 'rituals', + 'cadets', + 'extent', + 'roll', + 'keys', + 'frames', + 'smog', + 'violin', + 'cumin', + 'studs', + 'floor', + 'lockers', + 'recon', + 'city', + 'iguana', + 'tours', + 'daughter', + 'alpaca', + 'crop', + 'jammer', + 'plumbing', + 'blast', + 'cottages', + 'limeade', + 'lizard', + 'leash', + 'soaps', + 'scraps', + 'networks', + 'mane', + 'grandson', + 'detox', + 'cow', + 'dock', + 'admiral', + 'limit', + 'jock', + 'archery', + 'dollars', + 'colors', + 'swimwear', + 'tarps', + 'risk', + 'bolt', + 'inbox', + 'bee', + 'glades', + 'beaks', + 'tablet', + 'foes', + 'ransom', + 'deacon', + 'tour', + 'delay', + 'impacts', + 'paste', + 'mountains', + 'dragon', + 'wrist', + 'stench', + 'grills', + 'toggle', + 'noise', + 'tripods', + 'wish', + 'chef', + 'thinker', + 'chunks', + 'trash', + 'spell', + 'safety', + 'credential', + 'flake', + 'donation', + 'bonnets', + 'designer', + 'egret', + 'scratch', + 'worker', + 'outdoors', + 'suns', + 'jetty', + 'llama', + 'mimosa', + 'flypaper', + 'patina', + 'trunk', + 'tabasco', + 'distance', + 'blimp', + 'ridge', + 'prophecy', + 'yip', + 'scan', + 'actresses', + 'boys', + 'digit', + 'suitcase', + 'cranes', + 'sixties', + 'toucan', + 'landlady', + 'basket', + 'kiln', + 'zombies', + 'grandfather', + 'rye', + 'lawns', + 'kitty', + 'slipper', + 'robes', + 'hands', + 'flair', + 'drain', + 'pansy', + 'archive', + 'dikes', + 'mascara', + 'hooves', + 'crow', + 'footers', + 'cult', + 'impulse', + 'ingot', + 'pottery', + 'desk', + 'bong', + 'rhino', + 'clarinets', + 'fires', + 'vows', + 'bubble', + 'manhole', + 'cut', + 'ski', + 'chick', + 'produce', + 'belly', + 'eel', + 'glider', + 'copies', + 'dugout', + 'total', + 'panther', + 'hurdle', + 'scarcity', + 'decree', + 'kinsman', + 'goldfish', + 'peg', + 'expo', + 'cog', + 'bin', + 'cooks', + 'wills', + 'ego', + 'delta', + 'ounce', + 'militant', + 'chemists', + 'voters', + 'pig', + 'webs', + 'niece', + 'cape', + 'clinics', + 'nip', + 'prisoner', + 'yoke', + 'traumas', + 'pillow', + 'matter', + 'microphone', + 'loans', + 'tripod', + 'reject', + 'slush', + 'crawlers', + 'fluids', + 'protector', + 'braid', + 'climate', + 'preset', + 'wail', + 'staple', + 'reels', + 'node', + 'taunt', + 'jurist', + 'galley', + 'mirror', + 'artifact', + 'newton', + 'diamonds', + 'skirmish', + 'digs', + 'zone', + 'gash', + 'urgency', + 'vices', + 'oaths', + 'flood', + 'purses', + 'buffer', + 'ladle', + 'aces', + 'lava', + 'clove', + 'piano', + 'caption', + 'tedium', + 'janitors', + 'shed', + 'almanac', + 'postbox', + 'meerkat', + 'sandpit', + 'plate', + 'cello', + 'hose', + 'colas', + 'hit', + 'office', + 'mooch', + 'squatter', + 'rake', + 'cyclists', + 'hazards', + 'anteater', + 'job', + 'peck', + 'medal', + 'pianist', + 'bozo', + 'jaw', + 'pad', + 'temple', + 'stooge', + 'stop', + 'snipers', + 'purist', + 'respect', + 'sombrero', + 'cops', + 'trimmer', + 'reed', + 'krypton', + 'objective', + 'overcoat', + 'balcony', + 'tribes', + 'humps', + 'ruse', + 'womb', + 'venture', + 'ignition', + 'rehab', + 'cramp', + 'gloves', + 'anthills', + 'lawyer', + 'gatherer', + 'bird', + 'refinery', + 'crafter', + 'tic', + 'ponies', + 'mall', + 'magician', + 'trickle', + 'escapade', + 'falcons', + 'drops', + 'galleria', + 'sable', + 'tacks', + 'podium', + 'pinch', + 'crusader', + 'spoke', + 'addict', + 'lilac', + 'bulges', + 'screwdriver', + 'unifier', + 'horse', + 'chord', + 'snafu', + 'pumice', + 'yak', + 'teacup', + 'workers', + 'bases', + 'sear', + 'llamas', + 'rolls', + 'liquor', + 'cranks', + 'splices', + 'kinship', + 'surgery', + 'coaches', + 'scrap', + 'brim', + 'yam', + 'ledge', + 'poetry', + 'country', + 'sodas', + 'speeds', + 'sensors', + 'script', + 'ovary', + 'curling', + 'opacity', + 'rules', + 'rum', + 'nutcase', + 'groans', + 'stoppage', + 'ankles', + 'oak', + 'culprit', + 'pucker', + 'earl', + 'bunker', + 'divot', + 'kazoo', + 'balls', + 'rockfish', + 'roof', + 'healer', + 'burns', + 'mechanism', + 'example', + 'dander', + 'grief', + 'tuxedo', + 'claim', + 'undead', + 'felt', + 'steed', + 'tonic', + 'casket', + 'sari', + 'fan', + 'peace', + 'fantasy', + 'kerchief', + 'justice', + 'crags', + 'engine', + 'cardigan', + 'pattern', + 'lentil', + 'duration', + 'motive', + 'figure', + 'retread', + 'mortuary', + 'pooch', + 'plumber', + 'coast', + 'pennant', + 'loon', + 'works', + 'medicine', + 'types', + 'notices', + 'nanny', + 'algae', + 'stamina', + 'carbs', + 'chum', + 'feedback', + 'octaves', + 'buttons', + 'crock', + 'mayo', + 'anatomy', + 'sinners', + 'desires', + 'nunnery', + 'hoe', + 'linguini', + 'plaza', + 'teabag', + 'marlin', + 'tools', + 'parody', + 'doubts', + 'decline', + 'rears', + 'defect', + 'hurdles', + 'aquarium', + 'tamale', + 'monitor', + 'runway', + 'yells', + 'rewards', + 'view', + 'sandals', + 'sewer', + 'ovaries', + 'detours', + 'dam', + 'auction', + 'trances', + 'porthole', + 'inactivity', + 'lavender', + 'lens', + 'shows', + 'thigh', + 'peon', + 'poison', + 'misinformation', + 'filth', + 'zeros', + 'warrior', + 'lilt', + 'prefix', + 'bulge', + 'charcoal', + 'sleds', + 'moat', + 'arena', + 'prods', + 'quarters', + 'file', + 'preacher', + 'riptide', + 'kettles', + 'resort', + 'fuses', + 'couple', + 'sting', + 'daffodil', + 'coworker', + 'bells', + 'pickle', + 'hardware', + 'crouton', + 'lore', + 'blitz', + 'debate', + 'elitism', + 'armpit', + 'omens', + 'neuron', + 'accident', + 'delirium', + 'scab', + 'roach', + 'mazes', + 'pushpin', + 'sprite', + 'shore', + 'slurp', + 'souls', + 'voter', + 'heights', + 'stroller', + 'probes', + 'basins', + 'elves', + 'ending', + 'defeats', + 'pension', + 'forces', + 'strip', + 'ruts', + 'quarks', + 'auto', + 'bruises', + 'subset', + 'dialog', + 'passerby', + 'altar', + 'exporter', + 'skid', + 'golf', + 'leeches', + 'futons', + 'crown', + 'splinter', + 'cavalry', + 'hay', + 'blooper', + 'prisms', + 'opponent', + 'chirp', + 'prawns', + 'maze', + 'lands', + 'husbands', + 'camps', + 'glasses', + 'camera', + 'dress', + 'fez', + 'zap', + 'privacy', + 'ping', + 'showcase', + 'kale', + 'cent', + 'beets', + 'preamble', + 'urn', + 'granny', + 'cache', + 'raises', + 'hulk', + 'fields', + 'griddle', + 'gerbil', + 'rumor', + 'waves', + 'tenor', + 'wreck', + 'deputies', + 'magazine', + 'parkas', + 'flattery', + 'ox', + 'chests', + 'blanket', + 'alehouse', + 'ravines', + 'princess', + 'necks', + 'women', + 'raisins', + 'advice', + 'swarms', + 'samba', + 'daytime', + 'renewal', + 'jolts', + 'veto', + 'shorts', + 'promos', + 'emperor', + 'intro', + 'belt', + 'scribe', + 'basil', + 'avatar', + 'lamb', + 'agencies', + 'bog', + 'wasp', + 'grinch', + 'sax', + 'ward', + 'quadrant', + 'tomahawk', + 'sip', + 'string', + 'knocks', + 'cover', + 'destiny', + 'hydrant', + 'bologna', + 'cobras', + 'dorks', + 'stallion', + 'hangover', + 'molds', + 'sheep', + 'scum', + 'lairs', + 'maize', + 'thrower', + 'boutique', + 'nicotine', + 'goal', + 'cigars', + 'oracles', + 'castle', + 'boa', + 'ladders', + 'corn', + 'brows', + 'sum', + 'viaduct', + 'apostle', + 'observer', + 'slugs', + 'groin', + 'grip', + 'purifier', + 'neck', + 'reentry', + 'nebula', + 'wombs', + 'tech', + 'cartons', + 'party', + 'lunacy', + 'earmark', + 'smoke', + 'haven', + 'bone', + 'comments', + 'disposal', + 'chimp', + 'minx', + 'slab', + 'bulls', + 'neutron', + 'purse', + 'order', + 'setting', + 'threats', + 'skiff', + 'monotype', + 'psychic', + 'zeal', + 'longbow', + 'computer', + 'surplus', + 'drafts', + 'filters', + 'maverick', + 'lion', + 'atlas', + 'pump', + 'clique', + 'register', + 'scrubber', + 'measles', + 'tests', + 'trusts', + 'jungle', + 'sniper', + 'rugby', + 'salvage', + 'composers', + 'capsules', + 'part', + 'look', + 'theism', + 'bug', + 'oblivion', + 'splash', + 'owl', + 'employer', + 'flasks', + 'skewers', + 'clogs', + 'support', + 'pegs', + 'tee', + 'urge', + 'sis', + 'hive', + 'lung', + 'week', + 'fuzz', + 'badge', + 'mowers', + 'grubs', + 'genie', + 'provider', + 'antacids', + 'colts', + 'garnet', + 'taxis', + 'comets', + 'tarp', + 'wok', + 'comma', + 'waiter', + 'gourd', + 'clues', + 'clients', + 'yowls', + 'bookmark', + 'cask', + 'crease', + 'cuddle', + 'forks', + 'torch', + 'wedding', + 'magpie', + 'librarian', + 'sheets', + 'toad', + 'crimes', + 'demon', + 'thrush', + 'bean', + 'area', + 'falcon', + 'crevice', + 'eras', + 'handwork', + 'atrium', + 'odors', + 'shrapnel', + 'soup', + 'stat', + 'rate', + 'cash', + 'ding', + 'mutation', + 'bins', + 'pout', + 'gangway', + 'want', + 'casts', + 'caviar', + 'tarmac', + 'substance', + 'steam', + 'brute', + 'whiskey', + 'gasket', + 'vitamin', + 'helmets', + 'flub', + 'felons', + 'tinkle', + 'appetite', + 'liquid', + 'lashes', + 'forms', + 'liar', + 'remnant', + 'cider', + 'tires', + 'spools', + 'section', + 'accusation', + 'curls', + 'dome', + 'tether', + 'throne', + 'virtues', + 'tomes', + 'agenda', + 'foxes', + 'prison', + 'pamphlet', + 'biped', + 'cinder', + 'turtle', + 'clicker', + 'foxhole', + 'fusion', + 'brunch', + 'amulet', + 'suspect', + 'charger', + 'yurts', + 'pie', + 'movers', + 'events', + 'oboes', + 'cicada', + 'hotel', + 'galaxies', + 'peat', + 'muss', + 'criteria', + 'dish', + 'boxes', + 'revival', + 'varsity', + 'fridge', + 'cougars', + 'bind', + 'armful', + 'science', + 'canteen', + 'gizzard', + 'crutch', + 'ethanol', + 'handoff', + 'gallons', + 'sprawl', + 'exits', + 'hilt', + 'crystals', + 'cosmos', + 'logs', + 'corral', + 'parka', + 'researcher', + 'cousin', + 'nephew', + 'voice', + 'escapist', + 'earring', + 'does', + 'taboos', + 'trail', + 'snowplow', + 'soap', + 'memory', + 'fobs', + 'players', + 'self', + 'attic', + 'rump', + 'earwax', + 'puritan', + 'jocks', + 'scorpion', + 'duckling', + 'starch', + 'heaters', + 'glob', + 'crosses', + 'scare', + 'leader', + 'youth', + 'hearts', + 'jailers', + 'tropics', + 'digits', + 'kitchen', + 'hives', + 'kook', + 'molar', + 'custard', + 'spleen', + 'pushup', + 'paddle', + 'carafe', + 'dike', + 'tarts', + 'dowry', + 'insult', + 'paprika', + 'doom', + 'sides', + 'attorney', + 'sips', + 'climb', + 'kitchens', + 'battle', + 'banners', + 'bank', + 'lien', + 'crack', + 'notes', + 'baggage', + 'whisper', + 'tactics', + 'identity', + 'polygon', + 'cord', + 'leaps', + 'slabs', + 'record', + 'logos', + 'names', + 'swamp', + 'brims', + 'tub', + 'slug', + 'overtone', + 'vow', + 'hickory', + 'epiphany', + 'equinox', + 'giants', + 'meme', + 'dye', + 'bags', + 'joint', + 'salons', + 'plows', + 'bill', + 'satire', + 'tiaras', + 'gypsy', + 'face', + 'nouns', + 'mists', + 'spin', + 'iris', + 'siding', + 'pasture', + 'beaver', + 'clothing', + 'contest', + 'jarl', + 'roundup', + 'demeanor', + 'icons', + 'twigs', + 'post', + 'jitters', + 'speller', + 'sanctity', + 'gale', + 'custody', + 'flings', + 'prams', + 'porridge', + 'steps', + 'grids', + 'rook', + 'looter', + 'pastime', + 'reams', + 'curtsy', + 'tease', + 'flow', + 'birth', + 'skits', + 'pagers', + 'pebbles', + 'walnut', + 'check', + 'mobster', + 'yodel', + 'jars', + 'visit', + 'rubbers', + 'elevator', + 'contract', + 'candy', + 'thunderbolt', + 'swig', + 'savior', + 'railcar', + 'senders', + 'edibles', + 'bead', + 'thimble', + 'readers', + 'motion', + 'sulfide', + 'kelp', + 'rebels', + 'stains', + 'pits', + 'visas', + 'dweller', + 'pedigree', + 'jokes', + 'outpost', + 'thugs', + 'serpents', + 'spares', + 'sprites', + 'skull', + 'brigade', + 'leotard', + 'scrabble', + 'experts', + 'humor', + 'freebie', + 'ladybug', + 'commerce', + 'dismay', + 'seat', + 'document', + 'acting', + 'flags', + 'cough', + 'hip', + 'crust', + 'leap', + 'cornhusk', + 'coupons', + 'timber', + 'sonata', + 'punks', + 'vet', + 'offer', + 'wrester', + 'servers', + 'garland', + 'twine', + 'unit', + 'messes', + 'favors', + 'salary', + 'niche', + 'singer', + 'blogs', + 'purr', + 'squash', + 'journal', + 'freak', + 'papa', + 'pasta', + 'ceremony', + 'mauls', + 'model', + 'hanger', + 'scam', + 'gulps', + 'stanza', + 'sensor', + 'plunder', + 'bikes', + 'agate', + 'frock', + 'curves', + 'corgi', + 'creek', + 'cufflink', + 'toast', + 'nations', + 'dads', + 'thrills', + 'kitten', + 'swath', + 'tombs', + 'pecks', + 'crick', + 'beam', + 'quicksand', + 'washer', + 'cues', + 'deeds', + 'grunts', + 'lettuce', + 'firms', + 'locks', + 'compounds', + 'cycling', + 'flukes', + 'consoles', + 'abdomens', + 'aliment', + 'platform', + 'squeal', + 'beast', + 'loves', + 'guild', + 'gelatin', + 'slates', + 'fig', + 'rice', + 'stalks', + 'loan', + 'squirt', + 'hangar', + 'cruises', + 'jowls', + 'knack', + 'club', + 'decency', + 'linens', + 'periods', + 'criminal', + 'harmony', + 'threads', + 'creed', + 'fists', + 'board', + 'minefield', + 'sulfur', + 'stew', + 'wetsuit', + 'recliner', + 'yield', + 'alerts', + 'cobs', + 'drizzle', + 'group', + 'runs', + 'words', + 'jaguars', + 'magazines', + 'bride', + 'realm', + 'stair', + 'losses', + 'water', + 'torque', + 'synopsis', + 'springs', + 'skirt', + 'divinity', + 'ore', + 'seeds', + 'tree', + 'toss', + 'peel', + 'fish', + 'envelopes', + 'cans', + 'paw', + 'studies', + 'deskwork', + 'anise', + 'starfish', + 'problem', + 'expedition', + 'introvert', + 'spots', + 'honor', + 'lodge', + 'shots', + 'space', + 'boy', + 'bellies', + 'honey', + 'friends', + 'reflux', + 'kink', + 'tapestry', + 'gems', + 'span', + 'growls', + 'cereal', + 'show', + 'irritant', + 'packs', + 'rental', + 'veils', + 'postcard', + 'roads', + 'infantry', + 'bongo', + 'shacks', + 'efforts', + 'imps', + 'locale', + 'roadway', + 'chat', + 'label', + 'legwork', + 'mound', + 'legroom', + 'rotor', + 'times', + 'immunity', + 'roast', + 'wells', + 'dinners', + 'banjos', + 'twitch', + 'vacation', + 'stick', + 'moonwalk', + 'passport', + 'smudges', + 'venues', + 'chap', + 'synergy', + 'morals', + 'ride', + 'tutors', + 'tar', + 'bandage', + 'morale', + 'cosigner', + 'boars', + 'craving', + 'delicacy', + 'cables', + 'branch', + 'radar', + 'sublevel', + 'planet', + 'dirk', + 'grade', + 'bag', + 'serve', + 'remedies', + 'kayaks', + 'thrust', + 'rebates', + 'spas', + 'beauty', + 'skies', + 'abs', + 'heroism', + 'creeks', + 'arrival', + 'swimsuit', + 'cousins', + 'viewer', + 'pads', + 'labs', + 'launch', + 'purge', + 'twister', + 'fiddles', + 'pile', + 'moocher', + 'south', + 'tribe', + 'junk', + 'verbs', + 'spotter', + 'villages', + 'name', + 'shock', + 'cob', + 'dune', + 'bans', + 'fronds', + 'worm', + 'anchors', + 'deceit', + 'bleach', + 'moderator', + 'arch', + 'axes', + 'coasts', + 'tin', + 'jersey', + 'kinfolk', + 'dayroom', + 'outbreak', + 'felon', + 'cycle', + 'soloist', + 'mosaic', + 'ends', + 'mushroom', + 'runner', + 'pepper', + 'boots', + 'headwind', + 'bicep', + 'mister', + 'berms', + 'outtakes', + 'ladles', + 'stalk', + 'dams', + 'ram', + 'briar', + 'burp', + 'belts', + 'mafia', + 'noose', + 'brooms', + 'frogs', + 'servant', + 'tail', + 'matchbox', + 'chart', + 'worms', + 'gut', + 'shill', + 'opal', + 'gazebo', + 'watch', + 'snout', + 'step', + 'doubling', + 'jarhead', + 'dreams', + 'jargon', + 'biscuit', + 'critic', + 'zebras', + 'forges', + 'chemical', + 'angel', + 'cuts', + 'links', + 'razors', + 'anteaters', + 'mints', + 'procurer', + 'fans', + 'champions', + 'hub', + 'shank', + 'angler', + 'taxation', + 'rebirth', + 'creeps', + 'grocer', + 'wax', + 'nerds', + 'fake', + 'man', + 'conflicts', + 'teen', + 'thermos', + 'oceans', + 'beach', + 'brink', + 'presto', + 'barley', + 'vodka', + 'history', + 'bore', + 'laugh', + 'dill', + 'slobs', + 'cockpit', + 'donor', + 'shin', + 'hexagons', + 'bluff', + 'mug', + 'granola', + 'hermits', + 'crusade', + 'norm', + 'game', + 'escargot', + 'sharpie', + 'powers', + 'turner', + 'echoes', + 'lid', + 'ribs', + 'corsage', + 'latitude', + 'upstairs', + 'manes', + 'tricycle', + 'daisy', + 'sofas', + 'reviver', + 'leak', + 'storage', + 'impulses', + 'plays', + 'bud', + 'department', + 'pretext', + 'mat', + 'rep', + 'pact', + 'fryer', + 'hammock', + 'bull', + 'jests', + 'way', + 'spokes', + 'titbit', + 'dwelling', + 'crab', + 'cobra', + 'hobbies', + 'puns', + 'spur', + 'docks', + 'rudder', + 'jog', + 'twins', + 'historic', + 'trench', + 'managers', + 'camels', + 'fiddle', + 'noises', + 'cocoon', + 'zeppelin', + 'sulfite', + 'omnivore', + 'jukebox', + 'rockets', + 'fluke', + 'newt', + 'cinch', + 'scanner', + 'siesta', + 'blur', + 'parcels', + 'clam', + 'farmers', + 'blemishes', + 'wage', + 'daybed', + 'brawn', + 'tacking', + 'parmesan', + 'hut', + 'mugs', + 'tines', + 'chains', + 'decoy', + 'scope', + 'hue', + 'quark', + 'samples', + 'tables', + 'prune', + 'judo', + 'lesson', + 'fajita', + 'schools', + 'school', + 'blade', + 'antler', + 'tip', + 'ship', + 'thud', + 'karma', + 'sushi', + 'turban', + 'pebble', + 'flanks', + 'qualm', + 'advocate', + 'ghoul', + 'void', + 'artisan', + 'pea', + 'villain', + 'hull', + 'lasers', + 'writer', + 'pastrami', + 'sugar', + 'diet', + 'equipment', + 'sprout', + 'snore', + 'room', + 'columns', + 'septum', + 'stuffing', + 'grit', + 'earth', + 'ninjas', + 'passage', + 'tot', + 'headsman', + 'recap', + 'duels', + 'subsidy', + 'particle', + 'renegade', + 'doorknob', + 'rim', + 'lyrics', + 'combo', + 'modes', + 'wheel', + 'place', + 'dimple', + 'bubbles', + 'ball', + 'blame', + 'tweak', + 'vandal', + 'portion', + 'mules', + 'visors', + 'dash', + 'huntsman', + 'shuttle', + 'bullet', + 'sect', + 'hounds', + 'refill', + 'season', + 'spoof', + 'jumpers', + 'hobby', + 'tidings', + 'faction', + 'pride', + 'sabers', + 'feed', + 'sequence', + 'din', + 'act', + 'jar', + 'flux', + 'audits', + 'pupil', + 'con', + 'banister', + 'hardship', + 'speed', + 'profile', + 'jaguar', + 'flare', + 'populace', + 'educator', + 'spear', + 'friction', + 'fee', + 'deceiver', + 'ruses', + 'grub', + 'passenger', + 'menace', + 'toys', + 'idols', + 'dentists', + 'overbite', + 'monkey', + 'fights', + 'reply', + 'drive', + 'secretary', + 'dragster', + 'frolic', + 'blood', + 'macro', + 'teacher', + 'server', + 'haunch', + 'sizes', + 'tangle', + 'scales', + 'refund', + 'druids', + 'rank', + 'bankers', + 'circuses', + 'pushes', + 'payday', + 'foal', + 'shackle', + 'kilowatt', + 'shroud', + 'piglets', + 'trough', + 'squabs', + 'deluge', + 'fungus', + 'cluck', + 'battery', + 'impact', + 'gondola', + 'halls', + 'pock', + 'decks', + 'climbs', + 'barbs', + 'marine', + 'length', + 'tug', + 'vibe', + 'tram', + 'riches', + 'habit', + 'carnivals', + 'records', + 'grants', + 'master', + 'boulder', + 'badger', + 'assistant', + 'urology', + 'condor', + 'radio', + 'kerosene', + 'mood', + 'prunes', + 'whims', + 'pacifier', + 'veal', + 'plugs', + 'cursors', + 'virus', + 'birds', + 'cola', + 'notification', + 'precinct', + 'chaos', + 'mayday', + 'perks', + 'tightwad', + 'reefs', + 'mutants', + 'orchard', + 'scams', + 'bombers', + 'knots', + 'camp', + 'compilation', + 'dockyard', + 'lawyers', + 'sails', + 'shrouds', + 'couch', + 'category', + 'methods', + 'nutshell', + 'wart', + 'array', + 'drugs', + 'bunk', + 'shakes', + 'phases', + 'punk', + 'teeth', + 'flower', + 'travels', + 'relics', + 'peter', + 'mourner', + 'toe', + 'handclap', + 'valuables', + 'sheath', + 'soybean', + 'stud', + 'trait', + 'whisks', + 'hunt', + 'shopper', + 'quintet', + 'coke', + 'talc', + 'antidotes', + 'tulip', + 'cotton', + 'jaybird', + 'dandruff', + 'sarcasm', + 'hatchet', + 'summer', + 'freeway', + 'valves', + 'ark', + 'snail', + 'marmots', + 'knight', + 'antelope', + 'winnings', + 'protest', + 'reeds', + 'lottery', + 'inch', + 'sheen', + 'pants', + 'dot', + 'throats', + 'kites', + 'toes', + 'moss', + 'minutes', + 'curfew', + 'coward', + 'lobby', + 'lumber', + 'tone', + 'papyrus', + 'closet', + 'vixen', + 'salute', + 'nibble', + 'muffin', + 'cue', + 'tab', + 'rides', + 'waist', + 'docs', + 'spore', + 'stint', + 'daisies', + 'spark', + 'strips', + 'mates', + 'gamer', + 'user', + 'orbits', + 'excess', + 'examples', + 'bunch', + 'shredder', + 'math', + 'snakes', + 'subway', + 'region', + 'salsa', + 'sufferer', + 'hedgehog', + 'displays', + 'pity', + 'shard', + 'visa', + 'bunkers', + 'powwow', + 'door', + 'rivet', + 'giblet', + 'robe', + 'team', + 'hem', + 'slips', + 'crime', + 'mascots', + 'kayaker', + 'pubs', + 'rest', + 'anaconda', + 'levers', + 'prey', + 'dev', + 'format', + 'cellmate', + 'rower', + 'popes', + 'fizz', + 'enzyme', + 'overlord', + 'lakes', + 'bidet', + 'moths', + 'prologue', + 'commander', + 'jeep', + 'condo', + 'sandwich', + 'welts', + 'epoxy', + 'lotto', + 'dudes', + 'rot', + 'twig', + 'cross', + 'cockatoo', + 'dolt', + 'blender', + 'spam', + 'buoy', + 'start', + 'nag', + 'thumps', + 'unease', + 'hawks', + 'sketch', + 'enemies', + 'strobes', + 'halos', + 'bond', + 'rooky', + 'earpiece', + 'queen', + 'aroma', + 'cradles', + 'twilight', + 'togs', + 'defenses', + 'library', + 'pews', + 'armpits', + 'sand', + 'spite', + 'smears', + 'vehicle', + 'segment', + 'sandbar', + 'flop', + 'manual', + 'geese', + 'learner', + 'lab', + 'knives', + 'lining', + 'sites', + 'squirts', + 'referee', + 'teepee', + 'league', + 'stir', + 'road', + 'bane', + 'stray', + 'tiling', + 'crops', + 'artist', + 'whiz', + 'sauce', + 'sorts', + 'blush', + 'outcast', + 'gander', + 'traps', + 'peaks', + 'shortcut', + 'cable', + 'unions', + 'prisons', + 'margins', + 'monarch', + 'fall', + 'pools', + 'menus', + 'port', + 'marbles', + 'martyr', + 'barbers', + 'lily', + 'outing', + 'cashews', + 'chops', + 'seam', + 'rust', + 'lager', + 'styles', + 'love', + 'varnish', + 'tide', + 'lions', + 'boil', + 'vaults', + 'booth', + 'hackers', + 'lime', + 'hat', + 'sinew', + 'zombie', + 'dogs', + 'attics', + 'ripples', + 'laurel', + 'judge', + 'looters', + 'curl', + 'clerks', + 'spire', + 'dart', + 'bumps', + 'sultan', + 'cynic', + 'steer', + 'stores', + 'lady', + 'ales', + 'noun', + 'fib', + 'sacrifice', + 'sumo', + 'posse', + 'doe', + 'reboot', + 'rotunda', + 'anklet', + 'airline', + 'ale', + 'fang', + 'promo', + 'handrail', + 'landmass', + 'tent', + 'gloater', + 'priority', + 'rerun', + 'trance', + 'time', + 'fly', + 'lungs', + 'greed', + 'poppy', + 'pans', + 'nerve', + 'eon', + 'monoxide', + 'range', + 'dividers', + 'rigging', + 'clothes', + 'storm', + 'bung', + 'decades', + 'dibs', + 'reflex', + 'shrink', + 'tones', + 'pong', + 'hulls', + 'kick', + 'gateway', + 'gallows', + 'newspaper', + 'reptile', + 'deer', + 'grandpa', + 'eyelids', + 'clicks', + 'madam', + 'badges', + 'mob', + 'shield', + 'brawl', + 'livers', + 'jazz', + 'flotilla', + 'turtles', + 'notch', + 'goop', + 'king', + 'yarn', + 'punctuation', + 'chaplain', + 'broom', + 'larva', + 'process', + 'nylon', + 'shifter', + 'cacti', + 'berries', + 'polish', + 'furnace', + 'farmer', + 'soy', + 'factory', + 'landlord', + 'miss', + 'fleet', + 'snitch', + 'soils', + 'suds', + 'reel', + 'valley', + 'ghouls', + 'vitamins', + 'ranges', + 'walls', + 'pencil', + 'jest', + 'booty', + 'symbols', + 'earplugs', + 'contour', + 'catnip', + 'guide', + 'tendon', + 'daydream', + 'vagrancy', + 'lobster', + 'knife', + 'perjurer', + 'movie', + 'dividend', + 'bakers', + 'eggroll', + 'drums', + 'fawn', + 'shawl', + 'sidewalk', + 'shawls', + 'captions', + 'crepes', + 'splatter', + 'cottage', + 'cadet', + 'photo', + 'tory', + 'strength', + 'spectacle', + 'gymnast', + 'mange', + 'ties', + 'tiger', + 'vines', + 'shout', + 'buns', + 'reformer', + 'icon', + 'book', + 'cords', + 'shovel', + 'awls', + 'zebra', + 'chair', + 'vets', + 'prawn', + 'stance', + 'permit', + 'clown', + 'sow', + 'folds', + 'host', + 'bonfire', + 'twirls', + 'stilts', + 'suits', + 'claps', + 'dole', + 'vector', + 'ripcord', + 'mask', + 'hacks', + 'tray', + 'potion', + 'kiosks', + 'cynics', + 'titanium', + 'shadows', + 'organ', + 'grin', + 'page', + 'cell', + 'source', + 'footnote', + 'mites', + 'gunsmith', + 'endings', + 'fanatic', + 'flamingo', + 'refusal', + 'adherent', + 'visitor', + 'tap', + 'yokes', + 'tendency', + 'consumer', + 'robin', + 'competitor', + 'survivor', + 'government', + 'ace', + 'base', + 'silkworm', + 'spike', + 'synopses', + 'mama', + 'clip', + 'stay', + 'eve', + 'jawline', + 'scouts', + 'detour', + 'credit', + 'creels', + 'chaps', + 'month', + 'appendix', + 'stilt', + 'nobody', + 'sweats', + 'craze', + 'emerald', + 'peacock', + 'dragons', + 'pointer', + 'upgrade', + 'emotion', + 'scoops', + 'line', + 'morning', + 'bedpans', + 'feat', + 'clay', + 'blouse', + 'bait', + 'overflow', + 'specimen', + 'criticism', + 'jape', + 'moth', + 'victory', + 'pomp', + 'drill', + 'diamond', + 'talk', + 'rings', + 'tubes', + 'fedora', + 'episodes', + 'state', + 'skittles', + 'theme', + 'thrusts', + 'rule', + 'editors', + 'embolism', + 'coils', + 'hemlock', + 'omen', + 'jackal', + 'hornets', + 'dynasty', + 'kings', + 'things', + 'divorcee', + 'dresses', + 'hazard', + 'arbor', + 'pound', + 'flute', + 'countries', + 'couriers', + 'glass', + 'spiders', + 'overture', + 'jaunt', + 'shoal', + 'thrift', + 'elbow', + 'replay', + 'shrinks', + 'matron', + 'tomb', + 'onlooker', + 'anvils', + 'repose', + 'troops', + 'garden', + 'aisles', + 'anxiety', + 'roses', + 'orcs', + 'cud', + 'knock', + 'fail', + 'bench', + 'period', + 'rodents', + 'coconut', + 'hazelnut', + 'pug', + 'stubble', + 'poems', + 'skater', + 'winery', + 'laser', + 'girls', + 'mahogany', + 'distaste', + 'flight', + 'snags', + 'stocks', + 'awards', + 'lever', + 'function', + 'picks', + 'year', + 'corks', + 'shamrock', + 'ditch', + 'smells', + 'landmine', + 'jabs', + 'beams', + 'dolly', + 'pokers', + 'equity', + 'delegates', + 'brandy', + 'crumbs', + 'arborist', + 'vertigo', + 'pundit', + 'scimitar', + 'doves', + 'encampment', + 'curio', + 'jeers', + 'fathers', + 'archives', + 'duffel', + 'glue', + 'haiku', + 'holes', + 'watches', + 'vision', + 'buffet', + 'kibble', + 'petri', + 'tans', + 'coves', + 'index', + 'pitch', + 'cheer', + 'taco', + 'negotiator', + 'packet', + 'volumes', + 'troupe', + 'cur', + 'throws', + 'dogma', + 'vise', + 'railway', + 'flights', + 'search', + 'scrutiny', + 'paladin', + 'circlet', + 'virtue', + 'interest', + 'pot', + 'animator', + 'stature', + 'trifle', + 'rails', + 'medium', + 'aisle', + 'vista', + 'stamps', + 'winners', + 'stalls', + 'dishes', + 'ligament', + 'bassoon', + 'contests', + 'squab', + 'brat', + 'statue', + 'store', + 'jigsaw', + 'knobs', + 'bagels', + 'fuss', + 'security', + 'chairs', + 'glimmer', + 'aunt', + 'demand', + 'stunts', + 'spores', + 'baton', + 'deed', + 'life', + 'spits', + 'access', + 'queens', + 'pirate', + 'vein', + 'picnic', + 'knapsack', + 'recount', + 'bids', + 'stitch', + 'study', + 'melodies', + 'smelt', + 'sherry', + 'senior', + 'placemat', + 'cruncher', + 'mover', + 'footer', + 'watt', + 'sailor', + 'plots', + 'patio', + 'upswing', + 'stimuli', + 'vortex', + 'ethics', + 'bogs', + 'pretense', + 'feuds', + 'macaw', + 'click', + 'vest', + 'back', + 'treats', + 'eggnog', + 'finger', + 'orzo', + 'kiosk', + 'quills', + 'cruise', + 'deviancy', + 'romp', + 'planner', + 'evidence', + 'odor', + 'coral', + 'snowbird', + 'blasts', + 'yogis', + 'pack', + 'overseer', + 'list', + 'aviator', + 'barn', + 'centaur', + 'cashew', + 'roar', + 'forum', + 'growl', + 'snorts', + 'spaces', + 'charms', + 'module', + 'perm', + 'ravens', + 'ads', + 'hatchery', + 'hoaxes', + 'bro', + 'mural', + 'footing', + 'winks', + 'pursuit', + 'teargas', + 'blare', + 'racing', + 'inns', + 'whisky', + 'judges', + 'hook', + 'surface', + 'tourism', + 'jeans', + 'lipstick', + 'cluster', + 'lover', + 'nymph', + 'importer', + 'droplet', + 'goddess', + 'sneeze', + 'uniform', + 'answers', + 'eclair', + 'rags', + 'swirl', + 'weapon', + 'hitch', + 'seaweed', + 'whales', + 'ladder', + 'gourds', + 'phase', + 'seagull', + 'corporal', + 'machine', + 'member', + 'mulch', + 'monsieur', + 'fools', + 'vowel', + 'control', + 'beak', + 'people', + 'shrew', + 'elk', + 'scarves', + 'subfloor', + 'flatfoot', + 'remark', + 'tracer', + 'snag', + 'bowling', + 'plates', + 'parent', + 'clover', + 'sources', + 'crowd', + 'unrest', + 'clump', + 'angles', + 'embassy', + 'joggers', + 'pacifism', + 'turbines', + 'codex', + 'mesh', + 'silt', + 'excuses', + 'ranks', + 'designs', + 'filter', + 'crabmeat', + 'earlobe', + 'rind', + 'twinge', + 'parabola', + 'tails', + 'verse', + 'fossil', + 'vibes', + 'email', + 'explorer', + 'bow', + 'buck', + 'matcher', + 'quarrel', + 'caulk', + 'quiz', + 'payment', + 'figurine', + 'kicker', + 'crate', + 'outlet', + 'hash', + 'sludge', + 'den', + 'clink', + 'pew', + 'tactic', + 'bricks', + 'beards', + 'joyride', + 'radiator', + 'nose', + 'liter', + 'snack', + 'parades', + 'oxymoron', + 'aspirin', + 'pit', + 'eclairs', + 'swarm', + 'runt', + 'hassles', + 'snarl', + 'acorn', + 'mail', + 'huts', + 'knowledge', + 'gala', + 'champagne', + 'defiance', + 'screw', + 'malware', + 'metals', + 'geology', + 'drum', + 'fences', + 'tinsel', + 'growth', + 'turbans', + 'feminist', + 'landing', + 'armrest', + 'palms', + 'addicts', + 'proton', + 'helper', + 'brands', + 'vanes', + 'teamwork', + 'horn', + 'giggle', + 'houses', + 'laps', + 'odes', + 'piglet', + 'essay', + 'buckle', + 'throng', + 'erasure', + 'bonbons', + 'molars', + 'swings', + 'consumers', + 'rise', + 'barbecue', + 'ancestor', + 'vogue', + 'supplier', + 'moons', + 'footwork', + 'ground', + 'overhang', + 'harness', + 'papers', + 'serfs', + 'liberty', + 'markers', + 'pretzel', + 'memo', + 'greeting', + 'sweater', + 'clod', + 'win', + 'jogger', + 'war', + 'molecule', + 'vantage', + 'hugs', + 'spatula', + 'joker', + 'division', + 'mint', + 'sector', + 'mind', + 'welder', + 'pancake', + 'trader', + 'kisser', + 'hatred', + 'toll', + 'client', + 'flip', + 'raft', + 'cogs', + 'muskets', + 'soda', + 'driveway', + 'veneer', + 'hart', + 'employment', + 'axiom', + 'barber', + 'twist', + 'loss', + 'mead', + 'faculty', + 'ruble', + 'paranoia', + 'snowshoe', + 'census', + 'gloom', + 'dodo', + 'tank', + 'plywood', + 'creak', + 'spoils', + 'outs', + 'bodies', + 'motivation', + 'pollen', + 'lights', + 'jug', + 'taboo', + 'smith', + 'poncho', + 'jobs', + 'rancher', + 'cast', + 'fungi', + 'awning', + 'trick', + 'soot', + 'lawn', + 'heron', + 'spinster', + 'charity', + 'tact', + 'foothill', + 'oars', + 'turbofan', + 'piles', + 'blinker', + 'mist', + 'padding', + 'preface', + 'limits', + 'hamlets', + 'oysters', + 'enforcer', + 'chocolates', + 'sedan', + 'yodels', + 'wink', + 'retrial', + 'trot', + 'reliance', + 'archers', + 'shortage', + 'jeer', + 'choice', + 'winner', + 'jerk', + 'dens', + 'birthday', + 'meats', + 'buses', + 'weaver', + 'article', + 'chores', + 'shirt', + 'smash', + 'dog', + 'peril', + 'author', + 'town', + 'concrete', + 'fumble', + 'cherry', + 'cyclist', + 'showman', + 'bribe', + 'dances', + 'yowl', + 'agates', + 'hybrid', + 'ruler', + 'dancer', + 'nap', + 'kids', + 'rope', + 'silk', + 'silencer', + 'cells', + 'motives', + 'lace', + 'mumps', + 'prompter', + 'lagoons', + 'newbie', + 'cores', + 'loaves', + 'entity', + 'valet', + 'ploy', + 'parakeet', + 'weeds', + 'monarchy', + 'sheaths', + 'scorer', + 'nags', + 'apron', + 'squib', + 'follicle', + 'headlamp', + 'puddle', + 'bugs', + 'mantra', + 'slop', + 'liars', + 'fur', + 'wielder', + 'serves', + 'yogi', + 'clavicle', + 'budget', + 'monorail', + 'will', + 'sandbox', + 'riddle', + 'frog', + 'masses', + 'wand', + 'creases', + 'lances', + 'motors', + 'mule', + 'matrix', + 'bills', + 'drapery', + 'ravioli', + 'bays', + 'thought', + 'bolo', + 'hinges', + 'brads', + 'hug', + 'debates', + 'rubs', + 'percent', + 'sinks', + 'cannon', + 'tramps', + 'shame', + 'refunds', + 'fudge', + 'launcher', + 'maturity', + 'humus', + 'gluten', + 'stairs', + 'drips', + 'sausage', + 'grime', + 'wren', + 'circus', + 'density', + 'outrage', + 'rudders', + 'guy', + 'lemon', + 'taxes', + 'oxen', + 'bands', + 'license', + 'guitars', + 'till', + 'trainer', + 'doll', + 'fair', + 'orphans', + 'parish', + 'harps', + 'sardines', + 'parade', + 'samurai', + 'bass', + 'overtime', + 'antacid', + 'fissure', + 'cleft', + 'marrow', + 'gene', + 'vulture', + 'chest', + 'pulp', + 'graduate', + 'nutmeg', + 'mimic', + 'systems', + 'vase', + 'wins', + 'crayon', + 'patience', + 'bike', + 'burgers', + 'gem', + 'prowess', + 'crutches', + 'hole', + 'squeegee', + 'parrot', + 'founder', + 'bulletin', + 'igloo', + 'anchovy', + 'perk', + 'eternity', + 'tugboat', + 'chive', + 'trial', + 'latte', + 'rinses', + 'doorbell', + 'undertow', + 'nerves', + 'thrill', + 'suntan', + 'voodoo', + 'deities', + 'beaches', + 'stork', + 'scroll', + 'symphony', + 'lagoon', + 'duvet', + 'bikers', + 'critter', + 'bleep', + 'exes', + 'folk', + 'reins', + 'koala', + 'majesty', + 'scowl', + 'pixels', + 'sole', + 'museum', + 'lapse', + 'fastball', + 'spires', + 'planks', + 'set', + 'attire', + 'dosage', + 'waste', + 'graphics', + 'angels', + 'counting', + 'gardener', + 'sap', + 'fiend', + 'parlor', + 'prices', + 'umpire', + 'sage', + 'grower', + 'offices', + 'jackets', + 'calendars', + 'tiers', + 'eraser', + 'outlook', + 'zipper', + 'mamba', + 'care', + 'expert', + 'bucket', + 'rips', + 'tampons', + 'cheeses', + 'guff', + 'ear', + 'hobbit', + 'latches', + 'scuff', + 'timer', + 'carp', + 'arcade', + 'shop', + 'pins', + 'vole', + 'puck', + 'sculptor', + 'jumble', + 'barrier', + 'sister', + 'bladders', + 'upstroke', + 'task', + 'price', + 'harpist', + 'lark', + 'pyramid', + 'tampon', + 'truth', + 'boils', + 'savage', + 'wares', + 'purveyor', + 'moon', + 'fleets', + 'flagman', + 'tribunal', + 'preplan', + 'flea', + 'strudel', + 'tape', + 'pair', + 'bards', + 'jokester', + 'hours', + 'bonbon', + 'cleavers', + 'spider', + 'pun', + 'case', + 'polo', + 'dales', + 'roles', + 'cannons', + 'default', + 'boasts', + 'puzzles', + 'seniors', + 'headway', + 'tarot', + 'smell', + 'grits', + 'warden', + 'vests', + 'mischief', + 'issue', + 'shindig', + 'prep', + 'mic', + 'orca', + 'gender', + 'stranger', + 'poets', + 'film', + 'type', + 'clack', + 'abyss', + 'jumps', + 'segments', + 'fate', + 'senses', + 'utensil', + 'weeks', + 'maid', + 'marigold', + 'molasses', + 'research', + 'chapters', + 'cleric', + 'table', + 'caramel', + 'outfit', + 'knee', + 'deck', + 'denim', + 'giraffe', + 'daycare', + 'sprig', + 'czar', + 'letter', + 'caravan', + 'junkyard', + 'tribune', + 'organs', + 'knoll', + 'duo', + 'sermon', + 'windshield', + 'nodes', + 'cribs', + 'sycamore', + 'paints', + 'freewill', + 'vises', + 'sons', + 'relays', + 'bun', + 'erosion', + 'latch', + 'sprints', + 'hippie', + 'rockstar', + 'moped', + 'subtype', + 'wardrobe', + 'leases', + 'cart', + 'lunchbox', + 'calzone', + 'hangars', + 'courts', + 'adult', + 'kilobyte', + 'bible', + 'land', + 'deviant', + 'banshee', + 'fern', + 'story', + 'angle', + 'villa', + 'outlaw', + 'liver', + 'aorta', + 'cowls', + 'assistance', + 'beans', + 'moose', + 'invites', + 'chemicals', + 'mesas', + 'palm', + 'abdomen', + 'sigh', + 'volts', + 'bed', + 'canisters', + 'boon', + 'moonbeam', + 'culprits', + 'combs', + 'everyone', + 'flocks', + 'gesture', + 'footage', + 'stingray', + 'lamp', + 'press', + 'scarf', + 'mammary', + 'janitor', + 'demands', + 'robber', + 'stove', + 'tannery', + 'caddie', + 'pies', + 'swords', + 'snares', + 'chives', + 'grid', + 'course', + 'football', + 'nails', + 'talcum', + 'loot', + 'haste', + 'dawn', + 'heater', + 'teapots', + 'afterlife', + 'glance', + 'crates', + 'demons', + 'migrant', + 'discounts', + 'audiences', + 'beepers', + 'eardrum', + 'lumberjack', + 'spouts', + 'whip', + 'pounds', + 'concerts', + 'dunce', + 'cavern', + 'coins', + 'jerky', + 'mold', + 'sweat', + 'curtain', + 'halo', + 'lizards', + 'popcorn', + 'dispute', + 'cup', + 'wife', + 'eclipse', + 'ecology', + 'elms', + 'swab', + 'calories', + 'gifts', + 'flounder', + 'crayons', + 'mount', + 'tallow', + 'canoe', + 'voucher', + 'phobias', + 'ores', + 'optics', + 'bums', + 'arks', + 'sitter', + 'glitter', + 'blips', + 'helm', + 'diners', + 'propane', + 'teapot', + 'warning', + 'rampage', + 'plastic', + 'shrine', + 'venom', + 'turmeric', + 'servo', + 'landside', + 'diagrams', + 'estate', + 'jacket', + 'scallion', + 'slip', + 'mile', + 'cracker', + 'mayhem', + 'talons', + 'bistro', + 'nights', + 'sheet', + 'earache', + 'revision', + 'washout', + 'yacht', + 'inputs', + 'arms', + 'regret', + 'quotes', + 'roughage', + 'buyers', + 'citation', + 'trays', + 'boards', + 'ebook', + 'velvet', + 'soups', + 'breach', + 'butler', + 'semester', + 'bipod', + 'herbs', + 'skincare', + 'clock', + 'heft', + 'carton', + 'exorcist', + 'firm', + 'rabbit', + 'mutts', + 'dust', + 'defense', + 'essence', + 'runts', + 'broiler', + 'target', + 'jade', + 'storms', + 'pleasure', + 'blades', + 'wards', + 'cubes', + 'pickles', + 'beggar', + 'alarm', + 'bedroom', + 'delusion', + 'yogurt', + 'foothold', + 'gopher', + 'kilt', + 'hint', + 'tier', + 'strand', + 'eye', + 'dowel', + 'brokers', + 'fanfare', + 'luxury', + 'hedges', + 'alien', + 'dorm', + 'culture', + 'chalk', + 'army', + 'bloke', + 'tops', + 'rooms', + 'rubdown', + 'jams', + 'verdict', + 'mine', + 'spade', + 'lotus', + 'tax', + 'freckles', + 'apple', + 'revolts', + 'clutter', + 'glop', + 'desktop', + 'pictures', + 'rays', + 'tickle', + 'nerd', + 'header', + 'dose', + 'boom', + 'county', + 'nemesis', + 'tune', + 'sects', + 'lovers', + 'navies', + 'sleeve', + 'style', + 'patrol', + 'antennae', + 'pizza', + 'comrades', + 'brook', + 'lobe', + 'wildland', + 'trainee', + 'cricket', + 'covers', + 'scans', + 'meter', + 'skates', + 'bales', + 'whips', + 'sorcerer', + 'settler', + 'tear', + 'assembly', + 'repairs', + 'loaf', + 'piers', + 'pets', + 'foot', + 'finals', + 'curtains', + 'stinger', + 'cowl', + 'tack', + 'maids', + 'fruit', + 'armor', + 'trumpet', + 'annoyance', + 'age', + 'plans', + 'flame', + 'ware', + 'leaks', + 'opera', + 'sundae', + 'lives', + 'skins', + 'homeowner', + 'rumps', + 'hiker', + 'payphone', + 'weekend', + 'dean', + 'date', + 'licks', + 'herds', + 'nature', + 'critics', + 'canary', + 'stashes', + 'polka', + 'stoop', + 'streets', + 'lords', + 'holidays', + 'width', + 'pill', + 'spine', + 'pusher', + 'fragment', + 'layer', + 'dynamite', + 'liqueurs', + 'root', + 'thump', + 'envelope', + 'zoology', + 'sirens', + 'smocks', + 'tramp', + 'guys', + 'awl', + 'goals', + 'serpent', + 'pox', + 'skills', + 'chargers', + 'olives', + 'massager', + 'clots', + 'despair', + 'throttle', + 'gears', + 'hunch', + 'cowbird', + 'biker', + 'key', + 'imp', + 'gigabyte', + 'rivers', + 'trucker', + 'knights', + 'pipe', + 'stipend', + 'rival', + 'tricks', + 'hamper', + 'clank', + 'violins', + 'lease', + 'bronco', + 'supermom', + 'continent', + 'blimps', + 'tennis', + 'shrub', + 'hare', + 'bonanza', + 'jackals', + 'eagles', + 'hula', + 'leads', + 'traitor', + 'doorman', + 'colonist', + 'aid', + 'train', + 'reporter', + 'patriot', + 'venue', + 'traffic', + 'isotope', + 'activities', + 'score', + 'coach', + 'wool', + 'turnip', + 'cologne', + 'bros', + 'headache', + 'raps', + 'suet', + 'slit', + 'nursery', + 'dislike', + 'defender', + 'stash', + 'payroll', + 'spoons', + 'cupid', + 'doctors', + 'muscles', + 'obituary', + 'binder', + 'mutt', + 'absentee', + 'clan', + 'spades', + 'outback', + 'crowds', + 'uprising', + 'trousers', + 'places', + 'winch', + 'doors', + 'handcuff', + 'seed', + 'barb', + 'crouch', + 'utility', + 'mush', + 'proxy', + 'track', + 'tooth', + 'strains', + 'dollar', + 'actress', + 'ozone', + 'chump', + 'smiles', + 'autumn', + 'burrow', + 'baskets', + 'fugitive', + 'yeast', + 'vale', + 'shingle', + 'hope', + 'avocado', + 'flap', + 'aircraft', + 'hornet', + 'foods', + 'facts', + 'sprouts', + 'forts', + 'beer', + 'clipart', + 'atriums', + 'coot', + 'paths', + 'driver', + 'smuggler', + 'dope', + 'font', + 'carnival', + 'volt', + 'cycles', + 'glazing', + 'news', + 'revolt', + 'star', + 'gradient', + 'cowards', + 'headset', + 'hits', + 'release', + 'moms', + 'keno', + 'quip', + 'sunset', + 'trees', + 'copiers', + 'cliques', + 'tuft', + 'sexes', + 'iota', + 'poser', + 'traction', + 'shallot', + 'rhythm', + 'housing', + 'goggles', + 'devils', + 'daylight', + 'squares', + 'sesame', + 'pager', + 'wads', + 'policy', + 'deal', + 'inks', + 'juice', + 'coaster', + 'resin', + 'deli', + 'muskrat', + 'flavor', + 'cyst', + 'startup', + 'pacemaker', + 'arcades', + 'foam', + 'trinity', + 'wheels', + 'wash', + 'juicer', + 'overhaul', + 'claw', + 'auctions', + 'bar', + 'berry', + 'thicket', + 'swill', + 'applause', + 'foe', + 'rose', + 'nicks', + 'nieces', + 'disks', + 'linen', + 'orbs', + 'pouches', + 'licorice', + 'wildcard', + 'mankind', + 'ruins', + 'nest', + 'pecans', + 'diffuser', + 'poll', + 'burger', + 'streaks', + 'moves', + 'lies', + 'sorceress', + 'dwarf', + 'trapdoor', + 'unicorns', + 'dump', + 'sauces', + 'pats', + 'outsider', + 'sob', + 'barge', + 'sores', + 'shrines', + 'few', + 'marker', + 'cupcake', + 'robins', + 'totems', + 'flam', + 'eyebrow', + 'replies', + 'vineyard', + 'revenge', + 'rifling', + 'elephant', + 'purpose', + 'dice', + 'thorns', + 'prank', + 'quilts', + 'mess', + 'motorway', + 'yawn', + 'goldmine', + 'platinum', + 'colt', + 'gown', + 'banks', + 'probe', + 'dream', + 'equator', + 'skill', + 'consultant', + 'idiocy', + 'onward', + 'waffle', + 'bobcats', + 'griffon', + 'greeter', + 'margin', + 'mage', + 'celery', + 'octane', + 'mime', + 'faces', + 'bistros', + 'phrases', + 'palaces', + 'ibex', + 'tales', + 'map', + 'jetpack', + 'actions', + 'nests', + 'baritones', + 'swat', + 'makeover', + 'run', + 'students', + 'wine', + 'wonk', + 'debtor', + 'oxidant', + 'sled', + 'gauze', + 'brunt', + 'ashes', + 'warlock', + 'wigs', + 'vampire', + 'subtitle', + 'gongs', + 'pipeline', + 'trouble', + 'groan', + 'swamps', + 'weather', + 'heirloom', + 'valve', + 'hero', + 'fiber', + 'stunner', + 'lemur', + 'cuffs', + 'talisman', + 'cures', + 'cork', + 'touch', + 'jail', + 'shift', + 'phones', + 'nachos', + 'gravity', + 'juggler', + 'spinout', + 'manhunt', + 'spears', + 'seats', + 'choir', + 'chamber', + 'cultures', + 'years', + 'handyman', + 'idealist', + 'tassel', + 'pilgrim', + 'oar', + 'android', + 'mop', + 'lift', + 'height', + 'rail', + 'rouge', + 'tux', + 'pavement', + 'prudes', + 'pesos', + 'animal', + 'radios', + 'moonrise', + 'hump', + 'riveter', + 'uranium', + 'okra', + 'geek', + 'decibel', + 'turret', + 'guitar', + 'weasel', + 'myth', + 'subtotal', + 'borders', + 'chore', + 'tents', + 'crew', + 'bus', + 'inn', + 'files', + 'ivy', + 'grape', + 'parties', + 'grace', + 'grounds', + 'swipe', + 'tutor', + 'peanut', + 'pages', + 'decor', + 'litters', + 'waltz', + 'desks', + 'slaw', + 'spat', + 'question', + 'crests', + 'lot', + 'inches', + 'leverage', + 'motor', + 'friend', + 'raccoon', + 'jay', + 'stencil', + 'kin', + 'crag', + 'canals', + 'voltage', + 'thesis', + 'help', + 'keel', + 'coconuts', + 'spices', + 'sheds', + 'trip', + 'knolls', + 'reverend', + 'gripe', + 'refrain', + 'logic', + 'illness', + 'mass', + 'claims', + 'strides', + 'dunes', + 'wands', + 'flaw', + 'reunion', + 'topics', + 'gizmo', + 'shriek', + 'island', + 'denizen', + 'gruel', + 'overrun', + 'donator', + 'strike', + 'junkie', + 'rascal', + 'homes', + 'dials', + 'entryway', + 'curses', + 'alley', + 'robot', + 'perms', + 'ovum', + 'spoon', + 'remarks', + 'crypt', + 'oats', + 'pint', + 'repair', + 'vapors', + 'outhouse', + 'lice', + 'shape', + 'joy', + 'riot', + 'beau', + 'log', + 'limes', + 'bile', + 'pest', + 'visitors', + 'saga', + 'lapdog', + 'chimps', + 'cots', + 'plants', + 'login', + 'poultry', + 'moats', + 'valium', + 'composer', + 'tigers', + 'agent', + 'shrimp', + 'pegboard', + 'raisin', + 'saints', + 'options', + 'posts', + 'exchange', + 'tapes', + 'asp', + 'doorstep', + 'shove', + 'ideology', + 'sickle', + 'protons', + 'honks', + 'split', + 'throat', + 'wisp', + 'theory', + 'drams', + 'pores', + 'commando', + 'surname', + 'website', + 'husk', + 'loft', + 'tycoon', + 'albums', + 'bath', + 'juvenile', + 'kangaroo', + 'stabs', + 'shells', + 'artery', + 'areas', + 'resident', + 'seminar', + 'silicon', + 'analyzer', + 'napkin', + 'elf', + 'fool', + 'splints', + 'walrus', + 'digest', + 'wraith', + 'legume', + 'skewer', + 'outcome', + 'operator', + 'carol', + 'trapper', + 'airport', + 'moaner', + 'concert', + 'inchworm', + 'quarry', + 'clout', + 'mutiny', + 'peeks', + 'handsaw', + 'authors', + 'fowl', + 'wiper', + 'hunk', + 'break', + 'slaps', + 'tinker', + 'traces', + 'ramrod', + 'jowl', + 'capsule', + 'bunny', + 'sack', + 'cabs', + 'carrot', + 'saber', + 'silos', + 'manager', + 'spelling', + 'spread', + 'ferret', + 'ramen', + 'captain', + 'shale', + 'bang', + 'god', + 'duke', + 'wrench', + 'hogs', + 'covenant', + 'contents', + 'synapse', + 'calf', + 'captive', + 'nit', + 'world', + 'monks', + 'bikinis', + 'geeks', + 'printer', + 'poker', + 'mayor', + 'nuptials', + 'tube', + 'thorn', + 'spinner', + 'marinas', + 'dew', + 'mice', + 'comment', + 'stock', + 'lethargy', + 'screws', + 'tunes', + 'hikes', + 'lunch', + 'lard', + 'cereals', + 'flan', + 'rasp', + 'mockup', + 'wiretap', + 'yearling', + 'gimmick', + 'spirit', + 'bicycle', + 'huddle', + 'chipmunk', + 'astrology', + 'mongrel', + 'effect', + 'charisma', + 'democrat', + 'top', + 'heaps', + 'thug', + 'cliff', + 'castles', + 'wages', + 'holiday', + 'aqueduct', + 'athlete', + 'beagle', + 'coroner', + 'arrays', + 'element', + 'laptops', + 'plaster', + 'kegs', + 'teat', + 'sleet', + 'orcas', + 'embargo', + 'horns', + 'stems', + 'emporium', + 'cloth', + 'mammals', + 'objects', + 'rescuer', + 'commute', + 'calipers', + 'animals', + 'canyon', + 'hops', + 'broker', + 'sham', + 'bale', + 'panorama', + 'drinks', + 'rocket', + 'sweets', + 'cars', + 'lag', + 'hunks', + 'ritual', + 'cure', + 'fumes', + 'jinx', + 'bonnet', + 'knob', + 'taproot', + 'cows', + 'headgear', + 'rebuttal', + 'squid', + 'mutant', + 'pail', + 'ogres', + 'welt', + 'bulbs', + 'brushes', + 'ploys', + 'nacho', + 'risks', + 'plenty', + 'gas', + 'cabins', + 'photons', + 'scones', + 'symbol', + 'degrees', + 'rifts', + 'acrobats', + 'halogen', + 'wharf', + 'goats', + 'stylus', + 'bushes', + 'trampoline', + 'shave', + 'lentils', + 'quid', + 'sticks', + 'scalps', + 'suburb', + 'dentist', + 'strainer', + 'macaroni', + 'occupier', + 'proverb', + 'hoods', + 'hotels', + 'specks', + 'virgins', + 'shaft', + 'column', + 'jive', + 'aunts', + 'rods', + 'egos', + 'quail', + 'console', + 'mum', + 'jumper', + 'slogan', + 'movies', + 'dent', + 'sapling', + 'brochure', + 'quest', + 'tenure', + 'bakeries', + 'era', + 'stucco', + 'poet', + 'trucks', + 'opposite', + 'biology', + 'champ', + 'turns', + 'anthem', + 'expenses', + 'diameter', + 'labor', + 'cranium', + 'baking', + 'hymn', + 'hyena', + 'tubas', + 'bets', + 'plat', + 'twitter', + 'casinos', + 'salads', + 'owner', + 'chimes', + 'brew', + 'pang', + 'congress', + 'ropes', + 'pleat', + 'implant', + 'druid', + 'counties', + 'snips', + 'teriyaki', + 'crooks', + 'bottle', + 'playroom', + 'decal', + 'neighbor', + 'kidnaper', + 'stardom', + 'orange', + 'herd', + 'shrubs', + 'craft', + 'arrow', + 'family', + 'meteors', + 'method', + 'perfume', + 'egotism', + 'steroid', + 'flaps', + 'request', + 'rush', + 'starter', + 'refresh', + 'murmur', + 'discount', + 'chicken', + 'murals', + 'tots', + 'cherub', + 'dropout', + 'thrall', + 'pups', + 'router', + 'block', + 'employee', + 'dial', + 'dodos', + 'insect', + 'color', + 'strokes', + 'monk', + 'brood', + 'comic', + 'gowns', + 'unloader', + 'hell', + 'balms', + 'token', + 'narrator', + 'armband', + 'starship', + 'islands', + 'voyage', + 'libraries', + 'ginseng', + 'muses', + 'termite', + 'remover', + 'cartoon', + 'ribcage', + 'credits', + 'ingots', + 'labels', + 'lie', + 'oregano', + 'teens', + 'darkroom', + 'byway', + 'jailer', + 'stream', + 'poise', + 'pentagon', + 'pipes', + 'sanctum', + 'vats', + 'nugget', + 'nativity', + 'reburial', + 'loom', + 'hybrids', + 'fins', + 'crumpet', + 'troughs', + 'blossom', + 'blog', + 'item', + 'language', + 'breath', + 'ash', + 'campers', + 'gavel', + 'bumpers', + 'skipper', + 'corners', + 'dram', + 'fin', + 'grating', + 'guts', + 'clouds', + 'panes', + 'garb', + 'gains', + 'vagabond', + 'plume', + 'critters', + 'kite', + 'gauntlet', + 'counter', + 'drawl', + 'weirdo', + 'lounge', + 'snow', + 'app', + 'townhome', + 'bagpipes', + 'cats', + 'admirer', + 'guru', + 'tart', + 'cuff', + 'kimono', + 'elastic', + 'anglers', + 'thespian', + 'trout', + 'guzzler', + 'generator', + 'vocalist', + 'agents', + 'smithy', + 'zip', + 'text', + 'foyer', + 'peak', + 'rusk', + 'theology', + 'lapels', + 'nectar', + 'mobs', + 'query', + 'blaze', + 'avatars', + 'vial', + 'paycheck', + 'property', + 'food', + 'romance', + 'weld', + 'usher', + 'stacks', + 'raider', + 'bail', + 'conduit', + 'penknife', + 'archer', + 'bark', + 'headroom', + 'delegate', + 'slant', + 'slits', + 'berm', + 'swim', + 'pillbox', + 'plea', + 'kilts', + 'beat', + 'vat', + 'infant', + 'shrug', + 'alarms', + 'formula', + 'riddance', + 'eggs', + 'sense', + 'oligarch', + 'barrels', + 'skeleton', + 'booze', + 'grange', + 'evasion', + 'galaxy', + 'gaff', + 'ranches', + 'espresso', + 'mulberry', + 'wants', + 'bluffs', + 'vacancy', + 'fleas', + 'rocker', + 'slacker', + 'camel', + 'yell', + 'worry', + 'farmhouse', + 'meshes', + 'odds', + 'tongs', + 'urchin', + 'punt', + 'noodles', + 'inside', + 'lecture', + 'planes', + 'squat', + 'goods', + 'gumdrop', + 'jasmine', + 'oranges', + 'parsnip', + 'drug', + 'bites', + 'awnings', + 'swagger', + 'snouts', + 'supper', + 'lemurs', + 'pines', + 'charts', + 'prize', + 'footlocker', + 'jab', + 'sprigs', + 'grain', + 'eater', + 'denture', + 'bison', + 'details', + 'climates', + 'ladies', + 'arenas', + 'channel', + 'truce', + 'mustard', + 'crumb', + 'nomad', + 'reaction', + 'rift', + 'untruth', + 'coin', + 'damage', + 'gumbo', + 'faith', + 'fortress', + 'lemons', + 'roots', + 'whey', + 'streak', + 'glaucoma', + 'kiwi', + 'mimes', + 'nudist', + 'broth', + 'scalpel', + 'oases', + 'slats', + 'mutes', + 'troop', + 'slicer', + 'obscenity', + 'twit', + 'stoves', + 'tingle', + 'suitor', + 'sundress', + 'marble', + 'cactus', + 'wiring', + 'tad', + 'noel', + 'hairs', + 'stamp', + 'needle', + 'survival', + 'endnote', + 'funnel', + 'organism', + 'spans', + 'meeting', + 'test', + 'clog', + 'adults', + 'sash', + 'economy', + 'screens', + 'occupant', + 'seals', + 'juniper', + 'omission', + 'limbs', + 'hashes', + 'cement', + 'royalty', + 'marathon', + 'goblin', + 'spruce', + 'tags', + 'fife', + 'scorn', + 'globes', + 'heir', + 'gnats', + 'octagon', + 'redo', + 'miracle', + 'trident', + 'bust', + 'laborer', + 'cove', + 'flannels', + 'stage', + 'scallop', + 'cigar', + 'stroll', + 'creator', + 'facelift', + 'photos', + 'shoe', + 'nation', + 'grader', + 'trauma', + 'grins', + 'watermelon', + 'trustee', + 'freight', + 'genetics', + 'sinkers', + 'widow', + 'chicks', + 'tote', + 'granddad', + 'shorty', + 'antenna', + 'farce', + 'treasury', + 'coca', + 'kimonos', + 'hermit', + 'wind', + 'prayer', + 'heads', + 'rut', + 'strays', + 'battles', + 'hoody', + 'lodging', + 'mansion', + 'password', + 'demotion', + 'monster', + 'pelvis', + 'suite', + 'python', + 'filler', + 'trillion', + 'rioter', + 'glucose', + 'race', + 'goblins', + 'scars', + 'wonder', + 'epidural', + 'exam', + 'leashes', + 'pacifist', + 'relish', + 'parcel', + 'setback', + 'ducts', + 'producer', + 'staff', + 'garter', + 'gamble', + 'norms', + 'goof', + 'title', + 'cards', + 'bows', + 'bloat', + 'workload', + 'slider', + 'secrecy', + 'park', + 'demise', + 'church', + 'rear', + 'exec', + 'mayors', + 'muzzle', + 'tomcat', + 'teaspoon', + 'calamity', + 'onion', + 'costs', + 'medics', + 'crevices', + 'pane', + 'oops', + 'snaps', + 'rigor', + 'beasts', + 'graphs', + 'states', + 'remix', + 'cornea', + 'wafers', + 'goatee', + 'doc', + 'services', + 'legumes', + 'apes', + 'bandits', + 'sentry', + 'quips', + 'coating', + 'cabana', + 'spring', + 'haul', + 'seafood', + 'muck', + 'saves', + 'anthrax', + 'globe', + 'treasure', + 'cafe', + 'domain', + 'clerk', + 'climber', + 'pixie', + 'prodigy', + 'caddy', + 'apostles', + 'mumbling', + 'leech', + 'implants', + 'princes', + 'tacos', + 'conflict', + 'whale', + 'minimum', + 'boas', + 'mandate', + 'shack', + 'goat', + 'frame', + 'halves', + 'barriers', + 'opus', + 'sty', + 'dates', + 'finance', + 'embers', + 'code', + 'diagram', + 'poem', + 'harbor', + 'playoff', + 'mermaid', + 'desire', + 'nocks', + 'mounds', + 'ushers', + 'poplar', + 'sport', + 'rumors', + 'aphid', + 'husks', + 'animation', + 'riddles', + 'wanted', + 'deadbolt', + 'tiara', + 'bowl', + 'dyslexia', + 'basin', + 'brats', + 'dazzler', + 'tunic', + 'preview', + 'guest', + 'utopia', + 'side', + 'trunks', + 'duel', + 'rates', + 'bay', + 'tempo', + 'swigs', + 'cubicles', + 'taps', + 'branches', + 'zinc', + 'rock', + 'detail', + 'snooper', + 'temper', + 'stem', + 'drainer', + 'speech', + 'hills', + 'fort', + 'spender', + 'lass', + 'seer', + 'exiles', + 'lyre', + 'tome', + 'vanity', + 'meters', + 'toffee', + 'ogre', + 'errors', + 'sports', + 'copier', + 'scholar', + 'joules', + 'material', + 'hotdog', + 'widows', + 'tale', + 'wizard', + 'duds', + 'crayfish', + 'humanist', + 'swine', + 'pore', + 'dimples', + 'chant', + 'video', + 'spectrum', + 'pots', + 'bunches', + 'keep', + 'action', + 'maker', + 'ice', + 'stone', + 'giggles', + 'wealth', + 'brow', + 'hoop', + 'son', + 'tentacle', + 'loons', + 'spins', + 'nemo', + 'quarts', + 'poster', + 'recipe', + 'hemp', + 'exponent', + 'platter', + 'stump', + 'lures', + 'safes', + 'zones', + 'collars', + 'coots', + 'crabs', + 'hen', + 'varmint', + 'botanist', + 'meat', + 'brains', + 'pirates', + 'wig', + 'use', + 'glands', + 'acorns', + 'strap', + 'tweezers', + 'baseballs', + 'mommy', + 'agendas', + 'sass', + 'replica', + 'pests', + 'tilde', + 'milk', + 'sunlight', + 'crunch', + 'vastness', + 'relapse', + 'jackpot', + 'fund', + 'call', + 'nut', + 'cargo', + 'stylist', + 'status', + 'checks', + 'scout', + 'blister', + 'lanterns', + 'typist', + 'object', + 'sponge', + 'children', + 'truffle', + 'topic', + 'gecko', + 'epilogue', + 'lump', + 'flaws', + 'divots', + 'funds', + 'mixture', + 'impurity', + 'attendees', + 'plot', + 'slurs', + 'excerpt', + 'cults', + 'showroom', + 'yoyo', + 'hyphens', + 'showoff', + 'acids', + 'roost', + 'slide', + 'doorstop', + 'antidote', + 'skin', + 'fury', + 'qualms', + 'gunk', + 'nemeses', + 'fluid', + 'cowboy', + 'corridor', + 'twists', + 'goo', + 'laundry', + 'swirls', + 'glutton', + 'binders', + 'brain', + 'savages', + 'viola', + 'stumps', + 'sub', + 'pagoda', + 'microbe', + 'sneer', + 'morsel', + 'drainage', + 'seal', + 'argument', + 'butcher', + 'seams', + 'avenues', + 'mixes', + 'lure', + 'pliers', + 'arsenal', + 'disputes', + 'ape', + 'drunks', + 'tailor', + 'deployment', + 'railing', + 'tinfoil', + 'diner', + 'voices', + 'pedicure', + 'feud', + 'mascot', + 'brothers', + 'cap', + 'hunger', + 'distrust', + 'ferocity', + 'parsley', + 'machines', + 'mark', + 'spinach', + 'cod', + 'nucleus', + 'work', + 'message', + 'quart', + 'art', + 'racks', + 'safari', + 'osmosis', + 'geranium', + 'sprain', + 'grams', + 'toxin', + 'coal', + 'bridge', + 'might', + 'taxi', + 'steroids', + 'frond', + 'maul', + 'peas', + 'variety', + 'poses', + 'vine', + 'drip', + 'clumps', + 'rivulet', + 'hints', + 'update', + 'choices', + 'creation', + 'creature', + 'earwigs', + 'melon', + 'panel', + 'troll', + 'waters', + 'bouts', + 'prop', + 'outfield', + 'hacksaw', + 'irons', + 'sailors', + 'colander', + 'cub', + 'sandal', + 'fad', + 'skis', + 'peppers', + 'sobs', + 'calls', + 'banner', + 'bongs', + 'armories', + 'cents', + 'favor', + 'capitol', + 'share', + 'liftoff', + 'pesto', + 'earmuff', + 'canon', + 'shampoo', + 'casualty', + 'apostate', + 'tissues', + 'strain', + 'miner', + 'futon', + 'casino', + 'unicorn', + 'upstart', + 'spy', + 'showdown', + 'gap', + 'marshes', + 'flak', + 'crest', + 'iron', + 'shot', + 'optimist', + 'pajamas', + 'feather', + 'knuckles', + 'renter', + 'raptor', + 'revenue', + 'nana', + 'service', + 'pocket', + 'spook', + 'pantry', + 'boundary', + 'putty', + 'spree', + 'armoire', + 'moisture', + 'donkey', + 'skunk', + 'rant', + 'dinner', + 'poacher', + 'cupcakes', + 'sponsor', + 'exercise', + 'darts', + 'teas', + 'quests', + 'mace', + 'bribes', + 'defeat', + 'squeeze', + 'doorpost', + 'predator', + 'combat', + 'barns', + 'cabbage', + 'benches', + 'herald', + 'blizzards', + 'prism', + 'mill', + 'obstacle', + 'grass', + 'answer', + 'hoes', + 'siren', + 'treat', + 'traverse', + 'pockets', + 'vane', + 'snorkel', + 'elites', + 'lack', + 'crud', + 'fishbowl', + 'mollusk', + 'screen', + 'syndrome', + 'diary', + 'grades', + 'nick', + 'forest', + 'germs', + 'helmet', + 'tweets', + 'sulfate', + 'feline', + 'ban', + 'jet', + 'spikes', + 'draft', + 'cavity', + 'clowns', + 'buckets', + 'guidance', + 'navy', + 'amulets', + 'hubs', + 'corridors', + 'setup', + 'database', + 'getaway', + 'folks', + 'expanse', + 'grant', + 'detergent', + 'zoo', + 'pick', + 'months', + 'miners', + 'morality', + 'truck', + 'mote', + 'raise', + 'lullaby', + 'slime', + 'giveaway', + 'heists', + 'breeze', + 'toy', + 'trace', + 'goofball', + 'gait', + 'phone', + 'fray', + 'marches', + 'jam', + 'site', + 'knees', + 'find', + 'sales', + 'values', + 'painter', + 'overlap', + 'bard', + 'roasts', + 'strings', + 'odometer', + 'tiles', + 'candles', + 'stars', + 'badgers', + 'series', + 'duck', + 'huff', + 'axe', + 'git', + 'quill', + 'harbors', + 'eagle', + 'garters', + 'inlet', + 'cleaver', + 'coder', + 'pearl', + 'sandbag', + 'fountain', + 'guides', + 'blip', + 'demo', + 'jacks', + 'retreat', + 'depot', + 'vials', + 'mite', + 'device', + 'flashes', + 'cilantro', + 'canopy', + 'cherubs', + 'hasp', + 'curds', + 'tomboy', + 'pilot', + 'phoenix', + 'mouths', + 'hologram', + 'lecturer', + 'citizen', + 'student', + 'cloaks', + 'factor', + 'opossum', + 'clap', + 'sign', + 'anvil', + 'honk', + 'verb', + 'signal', + 'bruin', + 'clef', + 'queue', + 'bats', + 'screams', + 'hall', + 'vapor', + 'marina', + 'stimulus', + 'jesters', + 'rover', + 'brewery', + 'otters', + 'flask', + 'wire', + 'smasher', + 'dame', + 'joints', + 'muse', + 'palace', + 'steeple', + 'enquirer', + 'fiat', + 'maggot', + 'outburst', + 'plateau', + 'dowels', + 'stands', + 'titans', + 'wheat', + 'taste', + 'uses', + 'audit', + 'iodine', + 'garment', + 'ducks', + 'linseed', + 'latrine', + 'groove', + 'confetti', + 'rebate', + 'stones', + 'smile', + 'yard', + 'gristle', + 'corncob', + 'whoop', + 'veteran', + 'duty', + 'tomato', + 'patient', + 'manors', + 'reversal', + 'graph', + 'latex', + 'hamster', + 'optic', + 'crews', + 'lye', + 'ponds', + 'input', + 'germ', + 'boardroom', + 'swinger', + 'unicycle', + 'jerks', + 'point', + 'fight', + 'brick', + 'dory', + 'convents', + 'shirts', + 'debut', + 'finch', + 'peels', + 'zoos', + 'feeling', + 'prince', + 'pods', + 'stanzas', + 'vocation', + 'polenta', + 'updates', + 'lap', + 'weed', + 'swaps', + 'tarn', + 'elm', + 'hexagram', + 'chips', + 'otter', + 'value', + 'femur', + 'canal', + 'bib', + 'breeds', + 'heap', + 'ramp', + 'veil', + 'pan', + 'rubies', + 'havens', + 'fructose', + 'patch', + 'fiction', + 'ruckus', + 'drives', + 'spot', + 'witches', + 'joist', + 'saloon', + 'bruise', + 'stride', + 'datebook', + 'creep', + 'axon', + 'parking', + 'insects', + 'gadgets', + 'doormat', + 'snowfall', + 'backups', + 'parkway', + 'disorder', + 'cheeks', + 'cruiser', + 'shelf', + 'nephews', + 'cloves', + 'cartload', + 'java', + 'shoptalk', + 'mana', + 'familiar', + 'boast', + 'spill', + 'burrito', + 'sitcom', + 'soccer', + 'humans', + 'rinds', + 'hypnosis', + 'wires', + 'mowing', + 'ribbons', + 'creatures', + 'bauble', + 'refuge', + 'gremlin', + 'tackle', + 'peach', + 'karaoke', + 'cream', + 'groom', + 'subgroup', + 'splint', + 'dingo', + 'pleats', + 'monsoon', + 'woes', + 'putdown', + 'medic', + 'debt', + 'leeks', + 'husband', + 'igloos', + 'hype', + 'lord', + 'chords', + 'shapes', + 'display', + 'sun', + 'trophy', + 'police', + 'arches', + 'naps', + 'fibs', + 'squad', + 'alcoves', + 'troy', + 'turf', + 'bikini', + 'calendar', + 'ways', + 'body', + 'parks', + 'sin', + 'bat', + 'election', + 'fillet', + 'autos', + 'comb', + 'pita', + 'smock', + 'stings', + 'deputy', + 'puffs', + 'games', + 'habits', + 'premises', + 'banker', + 'prelude', + 'guard', + 'skit', + 'ratio', + 'shire', + 'bobcat', + 'subtext', + 'pelts', + 'sampling', + 'babies', + 'jockey', + 'ham', + 'laws', + 'jewelry', + 'slum', + 'fables', + 'ranger', + 'doornail', + 'gavels', + 'grave', + 'glare', + 'spawn', + 'chants', + 'modem', + 'daybreak', + 'street', + 'rage', + 'leggings', + 'biopsy', + 'note', + 'boiler', + 'negation', + 'jailbird', + 'earthquake', + 'choirs', + 'kisses', + 'bunks', + 'suit', + 'pike', + 'dime', + 'crook', + 'noses', + 'songs', + 'earthworm', + 'salsas', + 'plating', + 'rig', + 'cartel', + 'hexagon', + 'border', + 'stress', + 'buzzword', + 'sprint', + 'catacomb', + 'signs', + 'elders', + 'dojo', + 'props', + 'nail', + 'suffix', + 'fleece', + 'media', + 'box', + 'diets', + 'lads', + 'warmth', + 'cuckoo', + 'cradle', + 'ocelot', + 'beds', + 'walker', + 'flies', + 'skulls', + 'onset', + 'wane', + 'snoop', + 'cones', + 'bulb', + 'hankie', + 'tars', + 'evacuee', + 'routine', + 'eatery', + 'heart', + 'helium', + 'portal', + 'mud', + 'stink', + 'rag', + 'glitch', + 'junkman', + 'nurses', + 'copy', + 'outcomes', + 'recluse', + 'peons', + 'mantis', + 'visor', + 'diver', + 'yams', + 'drones', + 'enamel', + 'flogging', + 'lifter', + 'gals', + 'duff', + 'glamour', + 'levies', + 'dipper', + 'rebar', + 'fest', + 'theater', + 'patrols', + 'delays', + 'yoga', + 'wager', + 'jack', + 'network', + 'emphasis', + 'clinic', + 'canyons', + 'buffers', + 'virgin', + 'quartet', + 'lots', + 'skeptic', + 'invite', + 'sulk', + 'pole', + 'harvest', + 'pacts', + 'newts', + 'cane', + 'being', + 'maggots', + 'girl', + 'warp', + 'society', + 'gobs', + 'orb', + 'registry', + 'crewman', + 'faxes', + 'bugle', + 'postage', + 'bandit', + 'freaks', + 'wildcat', + 'perimeter', + 'wishes', + 'radish', + 'suffrage', + 'brad', + 'stand', + 'mother', + 'melody', + 'slice', + 'toil', + 'watts', + 'trios', + 'itch', + 'batons', + 'subject', + 'hazing', + 'pub', + 'wildfire', + 'tremor', + 'recess', + 'bungee', + 'dabs', + 'lists', + 'cufflinks', + 'ocean', + 'dashes', + 'trowel', + 'talks', + 'fads', + 'meteor', + 'baguette', + 'saws', + 'beret', + 'heading', + 'liquids', + 'axel', + 'witch', + 'pony', + 'pay', + 'motto', + 'image', + 'dud', + 'actor', + 'proposal', + 'kennel', + 'orbit', + 'gangs', + 'tongue', + 'director', + 'address', + 'quirk', + 'bishop', + 'tow', + 'lurch', + 'shafts', + 'units', + 'cutlass', + 'horses', + 'latrines', + 'trump', + 'energies', + 'diabetes', + 'teams', + 'vipers', + 'scurvy', + 'dad', + 'fencing', + 'needles', + 'cascade', + 'zippers', + 'surfer', + 'dumpster', + 'meals', + 'haze', + 'snuff', + 'baker', + 'sphere', + 'lulls', + 'gnu', + 'buffalos', + 'pagans', + 'graves', + 'squires', + 'births', + 'aphids', + 'cookie', + 'claws', + 'scents', + 'pin', + 'baths', + 'gliders', + 'aluminum', + 'field', + 'brutes', + 'tundra', + 'vestibule', + 'spouse', + 'ante', + 'universe', + 'tubs', + 'monopoly', + 'thumb', + 'travel', + 'almonds', + 'frosting', + 'relation', + 'races', + 'lather', + 'bully', + 'strife', + 'howls', + 'scheme', + 'mages', + 'proofs', + 'gong', + 'engraver', + 'noodle', + 'lyricism', + 'arts', + 'disaster', + 'thirst', + 'hubcaps', + 'sugars', + 'admin', + 'grading', + 'pod', + 'program', + 'errand', + 'spice', + 'crystal', + 'shake', + 'tire', + 'stardust', + 'future', + 'hardhead', + 'uncles', + 'fright', + 'fluff', + 'sea', + 'dilation', + 'sedative', + 'books', + 'haircut', + 'abacus', + 'kettle', + 'captains', + 'wall', + 'mugshot', + 'district', + 'specialist', + 'umpires', + 'web', + 'milkmaid', + 'litmus', + 'jewel', + 'playset', + 'maneuver', + 'lapel', + 'spheres', + 'dignity', + 'sod', + 'orc', + 'gerbils', + 'rigs', + 'entry', + 'sphinx', + 'dimes', + 'handler', + 'takes', + 'toads', + 'guards', + 'receiver', + 'hawk', + 'buds', + 'ovens', + 'pianos', + 'hoof', + 'boss', + 'shards', + 'mantle', + 'froth', + 'appetizer', + 'hyphen', + 'yearbook', + 'drains', + 'slash', + 'deflator', + 'wars', + 'cobweb', + 'nutrient', + 'law', + 'overlay', + 'clutch', + 'sacks', + 'showbiz', + 'sangria', + 'prizes', + 'overpass', + 'cities', + 'pho', + 'load', + 'tv', + 'physician', + 'surveyor', + 'uproar', + 'riverbed', + 'achievement', + 'lotion', + 'fare', + 'mare', + 'genders', + 'basement', + 'extras', + 'pains', + 'headband', + 'sediment', + 'vigil', + 'sock', + 'catalog', + 'closets', + 'bazooka', + 'pedals', + 'gully', + 'beet', + 'feathers', + 'recital', + 'tuba', + 'sharks', + 'footprint', + 'offers', + 'fakes', + 'barons', + 'court', + 'spec', + 'illusion', + 'spa', + 'zit', + 'throw', + 'antipasto', + 'parts', + 'natives', + 'buyer', + 'anthill', + 'grog', + 'bucks', + 'salami', + 'burps', + 'fault', + 'suspense', + 'blinkers', + 'bathtub', + 'wiki', + 'memento', + 'crank', + 'primer', + 'haunts', + 'facilities', + 'backs', + 'pigs', + 'cave', + 'hurray', + 'roulette', + 'reggae', + 'knot', + 'effects', + 'hackle', + 'stroke', + 'snacks', + 'flatworm', + 'surge', + 'gamers', + 'possum', + 'slap', + 'stops', + 'curve', + 'groves', + 'patron', + 'furs', + 'manor', + 'purchase', + 'totals', + 'helpers', + 'gossip', + 'ration', + 'rites', + 'pawn', + 'basis', + 'wino', + 'mucus', + 'orator', + 'yards', + 'fox', + 'rogues', + 'buckles', + 'pardon', + 'cairn', + 'grudges', + 'wipes', + 'content', + 'oat', + 'bulk', + 'matches', + 'legs', + 'seabird', + 'rafts', + 'arbors', + 'charities', + 'socks', + 'nips', + 'snails', + 'hearth', + 'grooves', + 'attendant', + 'mission', + 'tern', + 'medallion', + 'paper', + 'hooks', + 'notice', + 'max', + 'wisdom', + 'thighs', + 'flagpole', + 'drool', + 'fevers', + 'wimps', + 'lefty', + 'foil', + 'chambers', + 'plane', + 'wood', + 'eddy', + 'savanna', + 'starts', + 'hams', + 'posture', + 'event', + 'beef', + 'ohms', + 'floss', + 'outages', + 'mounts', + 'epidemic', + 'bola', + 'leek', + 'colony', + 'majority', + 'wraps', + 'maw', + 'aviators', + 'thanks', + 'today', + 'silo', + 'burr', + 'doctor', + 'cassette', + 'flu', + 'clarinet', + 'stopper', + 'exams', + 'platoon', + 'stake', + 'pangs', + 'centaurs', + 'mouth', + 'reminder', + 'jugular', + 'quote', + 'tadpole', + 'buzz', + 'juror', + 'nettle', + 'crescent', + 'ideas', + 'heckler', + 'batch', + 'parasite', + 'partner', + 'batches', + 'bandana', + 'hand', + 'lotions', + 'brand', + 'pumpkin', + 'magnolia', + 'pal', + 'developer', + 'handles', + 'jingle', + 'meet', + 'landline', + 'nuts', + 'parole', + 'stowaway', + 'gin', + 'cavities', + 'banking', + 'chard', + 'clips', + 'bookcase', + 'gates', + 'convict', + 'scamp', + 'huntress', + 'cases', + 'sets', + 'crafts', + 'grease', + 'bourbon', + 'guests', + 'alfalfa', + 'shuffle', + 'mobility', + 'forager', + 'guilds', + 'catapult', + 'exploit', + 'gaps', + 'avenue', + 'raffle', + 'graffiti', + 'parasail', + 'historian', + 'frat', + 'hens', + 'cleat', + 'habitant', + 'gator', + 'railroad', + 'headrest', + 'stool', + 'passion', + 'hill', + 'nub', + 'analyst', + 'inlets', + 'quirks', + 'frocks', + 'rickshaw', + 'brine', + 'perp', + 'cubicle', + 'crux', + 'wave', + 'warps', + 'wombats', + 'burn', + 'rodeos', + 'aria', + 'acrobat', + 'curator', + 'excuse', + 'frost', + 'drapes', + 'rink', + 'stages', + 'bell', + 'octets', + 'imposter', + 'yurt', + 'ruck', + 'curd', + 'syntax', + 'sinner', + 'dolls', + 'flames', + 'pinky', + 'wannabe', + 'yawns', + 'sprees', + 'bolts', + 'fencer', + 'canoes', + 'puzzle', + 'smear', + 'worlds', + 'package', + 'controls', + 'tyke', + 'hoot', + 'spills', + 'hike', + 'beeper', + 'pulses', + 'fiends', + 'canteens', + 'crib', + 'raven', + 'pup', + 'pens', + 'trivia', + 'pen', + 'tons', + 'marimba', + 'stunt', + 'aliens', + 'pine', + 'mastiff', + 'dingbat', + 'firewall', + 'walks', + 'shiv', + 'cylinder', + 'emus', + 'magma', + 'pain', + 'polkas', + 'maximum', + 'slump', + 'schoolboy', + 'banjo', + 'ranch', + 'comedy', + 'wreckage', + 'heritage', + 'legacy', + 'satchel', + 'silica', + 'sponges', + 'tipoff', + 'rack', + 'buddy', + 'citizens', + 'playmate', + 'shares', + 'capes', + 'tattoo', + 'outline', + 'lull', + 'house', + 'clickers', + 'tang', + 'prowler', + 'music', + 'drone', + 'ref', + 'witchcraft', + 'pier', + 'attendee', + 'campus', + 'tine', + 'afro', + 'grouch', + 'pose', + 'armchair', + 'blazes', + 'cuticle', + 'rhyme', + 'trinket', + 'info', + 'steward', + 'rearview', + 'grunt', + 'rinse', + 'lint', + 'woods', + 'upload', + 'musical', + 'silks', + 'senorita', + 'souvenir', + 'sonar', + 'grandma', + 'sucker', + 'simile', + 'emoticon', + 'squealer', + 'trials', + 'bakery', + 'spoiler', + 'seminars', + 'google', + 'seashell', + 'checkbook', + 'arrows', + 'eyes', + 'jester', + 'pacific', + 'cheers', + 'baristas', + 'flab', + 'throngs', + 'cheek', + 'species', + 'episode', + 'carrots', + 'pips', + 'diploma', + 'dents', + 'yelp', + 'clash', + 'marines', + 'idealism', + 'disdain', + 'soul', + 'emblem', + 'ferns', + 'blouses', + 'ruin', + 'dispatch', + 'backpack', + 'savings', + 'blight', + 'delusions', + 'weapons', + 'outreach', + 'turbojet', + 'mango', + 'rap', + 'baboons', + 'boat', + 'rinks', + 'meal', + 'points', + 'soil', + 'hitches', + 'hockey', + 'meow', + 'wildlife', + 'clang', + 'handful', + 'martini', + 'masts', + 'modules', + 'forearm', + 'ralph', + 'batteries', + 'punisher', + 'tile', + 'braids', + 'ease', + 'dirt', + 'cheddar', + 'winds', + 'nettles', + 'shell', + 'travesty', + 'fuse', + 'match', + 'democracy', + 'craw', + 'bars', + 'stratus', + 'mats', + 'manuals', + 'protester', + 'lofts', + 'gaze', + 'hummus', + 'tea', + 'cusp', + 'pucks', + 'coupon', + 'towel', + 'panama', + 'flecks', + 'exorcism', + 'rat', + 'sashes', + 'nibs', + 'figment', + 'wait', + 'flint', + 'phobia', + 'dealer', + 'companies', + 'wrath', + 'morons', + 'pectin', + 'ants', + 'instalment', + 'pampers', + 'blend', + 'proxies', + 'leaves', + 'surf', + 'pet', + 'sinker', + 'egg', + 'monogamy', + 'locker', + 'clams', + 'inventory', + 'sliver', + 'karate', + 'italics', + 'miso', + 'dangers', + 'mode', + 'oasis', + 'frenzy', + 'kiss', + 'edition', + 'traits', + 'freedom', + 'cages', + 'flavors', + 'decade', + 'mustang', + 'rookie', + 'cowboys', + 'mate', + 'tower', + 'devotee', + 'days', + 'alcove', + 'bookstore', + 'lyricist', + 'waitress', + 'pellets', + 'icepack', + 'handbook', + 'wits', + 'sables', + 'musket', + 'chime', + 'cafes', + 'peso', + 'oaks', + 'clans', + 'pond', + 'mills', + 'elite', + 'sneak', + 'avocados', + 'wedge', + 'tirade', + 'doorway', + 'stupor', + 'bears', + 'denials', + 'crybaby', + 'coil', + 'reps', + 'slur', + 'cubs', + 'pairs', + 'idea', + 'bump', + 'guardian', + 'croc', + 'studios', + 'mops', + 'dairy', + 'rune', + 'sound', + 'decimal', + 'elbows', + 'spray', + 'gum', + 'copilot', + 'kayak', + 'dropper', + 'grove', + 'technician', + 'jujitsu', + 'winters', + 'caravans', + 'scent', + 'upkeep', + 'potato', + 'flag', + 'tabloid', + 'divers', + 'districts', + 'oddity', + 'lasso', + 'moment', + 'smirks', + 'opals', + 'glow', + 'cheetah', + 'devil', + 'roaches', + 'sandfish', + 'sling', + 'dominoes', + 'cherries', + 'thumbs', + 'draw', + 'triceps', + 'sessions', + 'gal', + 'mistake', + 'rupture', + 'recoil', + 'gat', + 'flares', + 'patios', + 'humility', + 'users', + 'overview', + 'victim', + 'static', + 'build', + 'flour', + 'lout', + 'tofu', + 'priest', + 'feds', + 'nape', + 'customer', + 'deletion', + 'sequels', + 'trips', + 'clone', + 'payback', + 'coat', + 'footrest', + 'trap', + 'remedy', + 'bibs', + 'turn', + 'founding', + 'joystick', + 'celebrity', + 'saint', + 'slots', + 'crusher', + 'skier', + 'crash', + 'visits', + 'exit', + 'markets', + 'airplane', + 'boar', + 'sodium', + 'reverb', + 'loops', + 'print', + 'lobsters', + 'nook', + 'quotas', + 'design', + 'fist', + 'gizmos', + 'prom', + 'comrade', + 'dwarves', + 'denial', + 'healers', + 'widget', + 'ex', + 'nods', + 'interns', + 'hues', + 'song', + 'wombat', + 'ellipse', + 'emu', + 'torches', + 'sample', + 'commuter', + 'duct', + 'misses', + 'rainstorm', + 'lantern', + 'cornmeal', + 'plum', + 'glaze', + 'androids', + 'clubs', + 'pandemic', + 'contact', + 'burials', + 'ballet', + 'crows', + 'endpoint', + 'numbers', + 'petition', + 'slack', + 'hippo', + 'pranker', + 'adages', + 'wolf', + 'hack', + 'drama', + 'treatment', + 'gasp', + 'trek', + 'product', + 'tabs', + 'ketchup', + 'glues', + 'hairpin', + 'armory', + 'need', + 'goatskin', + 'capitols', + 'pop', + 'hoses', + 'coleslaw', + 'yolk', + 'rants', + 'detector', + 'mouse', + 'busts', + 'jawbone', + 'beads', + 'ninja', + 'notepad', + 'wreath', + 'spurs', + 'cattle', + 'baron', + 'ghosts', + 'dustpan', + 'schemes', + 'matador', + 'survey', + 'trapeze', + 'nickname', + 'prayers', + 'hips', + 'maps', + 'snip', + 'thing', + 'strands', + 'sundial', + 'hydrogen', + 'skimmer', + 'raids', + 'heels', + 'caboose', + 'sleigh', + 'chaff', + 'supply', + 'jump', + 'howl', + 'mix', + 'smudge', + 'trades', + 'flesh', + 'dawdler', + 'fax', + 'owls', + 'titan', + 'purebred', + 'earflap', + 'canvas', + 'hicks', + 'ruby', + 'musician', + 'staples', + 'champion', + 'grad', + 'elixir', + 'statute', + 'magnet', + 'hoard', + 'beeswax', + 'gadget', + 'fonts', + 'acid', + 'washroom', + 'sarong', + 'carb', + 'pause', + 'scrolls', + 'floods', + 'gran', + 'rally', + 'drink', + 'snippet', + 'editor', + 'manatee', + 'finisher', + 'kid', + 'barrel', + 'glacier', + 'waiver', + 'kinks', + 'danger', + 'runes', + 'lumps', + 'fares', + 'mothers', + 'infants', + 'conch', + 'hydrants', + 'vermin', + 'tunnels', + 'gyro', + 'handcart', + 'bacteria', + 'octopus', + 'butter', + 'padlock', + 'clamps', + 'headwear', + 'duress', + 'blemish', + 'playpen', + 'timing', + 'engines', + 'idioms', + 'baubles', + 'viper', + 'handgrip', + 'tweet', + 'octave', + 'wick', + 'bumper', + 'sniff', + 'skillet', + 'tusks', + 'washtub', + 'riders', + 'birch', + 'skydiver', + 'texts', + 'patches', + 'clue', + 'saw', + 'cost', + 'cucumber', + 'clerics', + 'anime', + 'fondue', + 'activity', + 'coop', + 'videos', + 'gnomes', + 'regions', + 'stoner', + 'lad', + 'skate', + 'legend', + 'gravel', + 'moles', + 'havoc', + 'blurb', + 'premium', + 'belches', + 'lip', + 'landmark', + 'remorse', + 'depth', + 'scone', + 'scotch', + 'voles', + 'minute', + 'stack', + 'warts', + 'singers', + 'drudge', + 'hijacker', + 'pavilion', + 'forehead', + 'dryad', + 'cravings', + 'webcam', + 'ebooks', + 'masks', + 'cliffs', + 'orphan', + 'pool', + 'glowworm', + 'intern', + 'chariots', + 'menu', + 'shadow', + 'wagon', + 'download', + 'tusk', + 'numeral', + 'braces', + 'napkins', + 'dive', + 'toilet', + 'bones', + 'tibia', + 'pancakes', + 'gutter', + 'marinade', + 'farm', + 'potions', + 'cracks', + 'animators', + 'ragweed', + 'linguist', + 'thread', + 'footgear', + 'plug', + 'creeds', + 'asteroid', + 'humorist', + 'slope', + 'apples', + 'apricots', + 'oxygen', + 'handling', + 'jewels', + 'vendor', + 'scene', + 'scads', + 'buffalo', + 'radiance', + 'trust', + 'willow', + 'camper', + 'swivel', + 'hop', + 'final', + 'wound', + 'core', + 'charlatan', + 'podcast', + 'reef', + 'tips', + 'glove', + 'magnets', + 'footpath', + 'bladder', + 'bot', + 'plant', + 'jurors', + 'circle', + 'faucet', + 'fog', + 'burg', + 'violator', + 'dove', + 'dolphin', + 'rungs', + 'penny', + 'hog', + 'tulips', + 'perch', + 'hangout', + 'size', + 'clocks', + 'gulf', + 'lunches', + 'shops', + 'stag', + 'cramps', + 'window', + 'data', + 'decoys', + 'day', + 'stadium', + 'deviator', + 'cinema', + 'gnome', + 'items', + 'kit', + 'ton', + 'wipe', + 'shanty', + 'plasma', + 'fears', + 'noon', + 'struggle', + 'truism', + 'jolt', + 'pastor', + 'deferral', + 'cause', + 'slants', + 'skyline', + 'spies', + 'papaya', + 'bum', + 'onions', + 'juncture', + 'pops', + 'mom', + 'marsh', + 'tells', + 'finalist', + 'tissue', + 'fold', + 'sands', + 'snowball', + 'soak', + 'garnish', + 'vault', + 'glances', + 'jets', + 'bevy', + 'armies', + 'end', + 'grandkid', + 'storks', + 'arc', + 'fender', + 'gob', + 'clashes', + 'tights', + 'slowpoke', + 'progress', + 'exposure', + 'cheater', + 'crowbar', + 'information', + 'coasters', + 'teenager', + 'biplane', + 'north', + 'square', + 'health', + 'tuna', + 'chasm', + 'violets', + 'charters', + 'exterior', + 'cloak', + 'talker', + 'rip', + 'fabric', + 'curler', + 'compound', + 'dairies', + 'powder', + 'sauna', + 'blob', + 'slums', + 'sisters', + 'backup', + 'rent', + 'moor', + 'wrinkle', + 'risotto', + 'stuff', + 'wrists', + 'pledge', + 'windows', + 'cartels', + 'pints', + 'garlic', + 'sky', + 'antiques', + 'tort', + 'pecan', + 'curse', + 'malls', + 'kilns', + 'gasps', + 'shade', + 'manpower', + 'filing', + 'rattle', + 'typo', + 'bush', + 'actors', + 'fable', + 'coffee', + 'scabs', + 'comedies', + 'trains', + 'drills', + 'collage', + 'fiasco', + 'vent', + 'errands', + 'alpacas', + 'flax', + 'salmon', + 'vigor', + 'cinemas', + 'mammal', + 'swimmer', + 'mandarin', + 'munchkin', + 'boost', + 'roux', + 'phrase', + 'option', + 'gentleman', + 'child', + 'ant', + 'contracts', + 'devotion', + 'oxford', + 'phrasing', + 'pulse', + 'relay', + 'dough', + 'drought', + 'jaws', + 'writ', + 'glade', + 'cabin', + 'cop', + 'chaw', + 'tag', + 'vendetta', + 'balm', + 'classes', + 'canopies', + 'motes', + 'rents', + 'button', + 'circles', + 'arm', + 'head', + 'pleas', + 'steamboat', + 'biz', + 'primate', + 'prude', + 'hanky', + 'granite', + 'tugs', + 'etching', + 'ream', + 'cleats', + 'geometry', + 'emission', + 'purity', + 'hick', + 'shoes', + 'usage', + 'gel', + 'pass', + 'kilogram', + 'binoculars', + 'mullets', + 'snooze', + 'doughboy', + 'polymer', + 'genes', + 'term', + 'lines', + 'rib', + 'oldie', + 'chalice', + 'nubs', + 'memes', + 'degree', + 'empathy', + 'trade', + 'zodiac', + 'altars', + 'spells', + 'scoop', + 'canes', + 'umbrella', + 'spiral', + 'anchor', + 'pearls', + 'snowman', + 'swan', + 'pupa', + 'puppy', + 'logo', + 'cringe', + 'axis', + 'fever', + 'plank', + 'wizards', + 'hunters', + 'banana', + 'bunt', + 'woman', + 'peroxide', + 'oven', + 'sofa', + 'broncos', + 'reasons', + 'crimp', + 'residue', + 'sink', + 'decals', + 'feta', + 'wimp', + 'limb', + 'minds', + 'soaks', + 'chute', + 'fir', + 'pillar', + 'gram', + 'spines', + 'salt', + 'hex', + 'mania', + 'chit', + 'ewe', + 'tie', + 'gauge', + 'compost', + 'talon', + 'hutch', + 'charm', + 'fauna', + 'graders', + 'dollop', + 'company', + 'roosts', + 'praise', + 'scammer', + 'yetis', + 'pace', + 'delivery', + 'cameo', + 'chunk', + 'donors', + 'ditches', + 'strategy', + 'keg', + 'tartar', + 'locusts', + 'liqueur', + 'brace', + 'rug', + 'beings', + 'looks', + 'blubber', + 'gif', + 'turbine', + 'pumps', + 'pyre', + 'blobs', + 'gill', + 'tiff', + 'thuds', + 'hides', + 'stable', + 'domes', + 'spacebar', + 'gull', + 'tango', + 'finish', + 'mongoose', + 'system', + 'citadel', + 'scandal', + 'astronaut', + 'drop', + 'veins', +] diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/server-name.dialog.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/server-name.dialog.ts index 5b017d57b..9bb7ea012 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/general/server-name.dialog.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/general/server-name.dialog.ts @@ -1,7 +1,12 @@ import { Component } from '@angular/core' import { FormsModule } from '@angular/forms' -import { i18nPipe, normalizeHostname } from '@start9labs/shared' -import { TuiButton, TuiDialogContext, TuiInput } from '@taiga-ui/core' +import { + i18nPipe, + normalizeHostname, + normalizeHostnameRaw, + randomServerName, +} from '@start9labs/shared' +import { TuiButton, TuiDialogContext, TuiError, TuiInput } from '@taiga-ui/core' import { injectContext } from '@taiga-ui/polymorpheus' @Component({ @@ -9,15 +14,28 @@ import { injectContext } from '@taiga-ui/polymorpheus' + - @if (name.trim()) { + @if (hostnameError) { + + } @else if (name.trim()) {

{{ normalizeHostname(name) }}.local

}
-
@@ -35,7 +53,7 @@ import { injectContext } from '@taiga-ui/polymorpheus' margin-top: 1.5rem; } `, - imports: [FormsModule, TuiButton, TuiInput, i18nPipe], + imports: [FormsModule, TuiButton, TuiError, TuiInput, i18nPipe], }) export class ServerNameDialog { private readonly context = @@ -49,6 +67,22 @@ export class ServerNameDialog { name = this.context.data.initialName readonly normalizeHostname = normalizeHostname + get hostnameError(): string | null { + const name = this.name.trim() + if (!name) return null + + const hostname = normalizeHostnameRaw(name) + + if (hostname.length < 4) return 'Hostname must be at least 4 characters' + if (hostname.length > 63) return 'Hostname must be 63 characters or less' + + return null + } + + randomizeName() { + this.name = randomServerName() + } + cancel() { this.context.completeWith(null) } diff --git a/web/projects/ui/src/app/services/api/api.fixures.ts b/web/projects/ui/src/app/services/api/api.fixures.ts index 0720fcfa3..4d7d5123b 100644 --- a/web/projects/ui/src/app/services/api/api.fixures.ts +++ b/web/projects/ui/src/app/services/api/api.fixures.ts @@ -1,12 +1,12 @@ +import { GetPackagesRes } from '@start9labs/marketplace' +import { ISB, IST, T } from '@start9labs/start-sdk' import { InstalledState, PackageDataEntry, } from 'src/app/services/patch-db/data-model' -import { ActionRes } from './api.types' -import { BTC_ICON, LND_ICON, PROXY_ICON, REGISTRY_ICON } from './api-icons' import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec' -import { T, ISB, IST } from '@start9labs/start-sdk' -import { GetPackagesRes } from '@start9labs/marketplace' +import { BTC_ICON, LND_ICON, PROXY_ICON, REGISTRY_ICON } from './api-icons' +import { ActionRes } from './api.types' import markdown from './md-sample.md' @@ -33,14 +33,14 @@ export namespace Mock { '0.4.1': { headline: 'v0.4.1', releaseNotes: 'Testing some release notes', - sourceVersion: '>=0.3.5:0 <=0.3.6-alpha.17:0', + sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.17:0', authorized: ['G24CSA5HNYEPIXJNMK7ZM4KD5SX5N6X4'], iso: {}, squashfs: { aarch64: { publishedAt: '2025-03-21T23:55:29.583006392Z', urls: [ - 'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_aarch64.squashfs', + 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_aarch64.squashfs', ], commitment: { hash: 'OUnANnZePtf7rSbj38JESl+iJAV0z0aiZ4opCiwpGbo=', @@ -54,7 +54,7 @@ export namespace Mock { 'aarch64-nonfree': { publishedAt: '2025-03-21T23:56:38.299572946Z', urls: [ - 'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_aarch64-nonfree.squashfs', + 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_aarch64-nonfree.squashfs', ], commitment: { hash: '6k+0RcyRQV+5A+h06OqpHxd4IT6IlFkfdy9dfHIP90c=', @@ -68,7 +68,7 @@ export namespace Mock { raspberrypi: { publishedAt: '2025-03-22T00:08:17.083064390Z', urls: [ - 'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_raspberrypi.squashfs', + 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_raspberrypi.squashfs', ], commitment: { hash: 'K+XuTZxo1KVsKjNSV8PPOMruCvAEZwerF9mbpFl53Gk=', @@ -82,7 +82,7 @@ export namespace Mock { x86_64: { publishedAt: '2025-03-22T00:05:57.684319247Z', urls: [ - 'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_x86_64.squashfs', + 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_x86_64.squashfs', ], commitment: { hash: '3UVkx3TQMBPlSU1OnV48Om9vjjA3s+Nk6dX3auYGpBo=', @@ -96,7 +96,7 @@ export namespace Mock { 'x86_64-nonfree': { publishedAt: '2025-03-22T00:07:11.893777122Z', urls: [ - 'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_x86_64-nonfree.squashfs', + 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_x86_64-nonfree.squashfs', ], commitment: { hash: 'IS1gJ56n/HlQqFbl1upMOAtLxyxB0cY0H89Ha+9h1lE=', @@ -454,7 +454,7 @@ export namespace Mock { marketingUrl: 'https://bitcoin.org', docsUrls: ['https://bitcoin.org'], releaseNotes: 'Even better support for Bitcoin and wallets!', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: BTC_ICON, @@ -496,7 +496,7 @@ export namespace Mock { marketingUrl: 'https://bitcoinknots.org', docsUrls: ['https://bitcoinknots.org'], releaseNotes: 'Even better support for Bitcoin and wallets!', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: BTC_ICON, @@ -548,7 +548,7 @@ export namespace Mock { marketingUrl: 'https://bitcoin.org', docsUrls: ['https://bitcoin.org'], releaseNotes: 'Even better support for Bitcoin and wallets!', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: BTC_ICON, @@ -590,7 +590,7 @@ export namespace Mock { marketingUrl: 'https://bitcoinknots.org', docsUrls: ['https://bitcoinknots.org'], releaseNotes: 'Even better support for Bitcoin and wallets!', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: BTC_ICON, @@ -644,7 +644,7 @@ export namespace Mock { marketingUrl: 'https://lightning.engineering/', docsUrls: ['https://lightning.engineering/'], releaseNotes: 'Upstream release to 0.17.5', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: LND_ICON, @@ -699,7 +699,7 @@ export namespace Mock { marketingUrl: 'https://lightning.engineering/', docsUrls: ['https://lightning.engineering/'], releaseNotes: 'Upstream release to 0.17.4', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: LND_ICON, @@ -758,7 +758,7 @@ export namespace Mock { marketingUrl: 'https://bitcoin.org', docsUrls: ['https://bitcoin.org'], releaseNotes: 'Even better support for Bitcoin and wallets!', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: BTC_ICON, @@ -800,7 +800,7 @@ export namespace Mock { marketingUrl: 'https://bitcoinknots.org', docsUrls: [], releaseNotes: 'Even better support for Bitcoin and wallets!', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: BTC_ICON, @@ -852,7 +852,7 @@ export namespace Mock { marketingUrl: 'https://lightning.engineering/', docsUrls: [], releaseNotes: 'Upstream release and minor fixes.', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: LND_ICON, @@ -907,7 +907,7 @@ export namespace Mock { docsUrls: [], marketingUrl: '', releaseNotes: 'Upstream release and minor fixes.', - osVersion: '0.3.6', + osVersion: '0.4.0', sdkVersion: '0.4.0-beta.49', gitHash: 'fakehash', icon: PROXY_ICON, @@ -1013,7 +1013,7 @@ export namespace Mock { createdAt: '2019-12-26T14:20:30.872Z', code: 2, level: 'success', - title: 'Welcome to StartOS 0.3.6!', + title: 'Welcome to StartOS 0.4.0!', message: 'Click "View Details" to learn all about the new version', data: markdown, seen: false, @@ -1207,7 +1207,7 @@ export namespace Mock { '1234-5678-9876-5432': { hostname: 'adjective-noun', timestamp: new Date().toISOString(), - version: '0.3.6', + version: '0.4.0', passwordHash: // password is asdfasdf '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', @@ -1247,7 +1247,7 @@ export namespace Mock { '1234-5678-9876-5432': { hostname: 'adjective-noun', timestamp: new Date().toISOString(), - version: '0.3.6', + version: '0.4.0', passwordHash: // password is asdfasdf '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', @@ -1282,7 +1282,7 @@ export namespace Mock { // startOs: { // abcdefgh: { // hostname: 'adjective-noun.local', - // version: '0.3.6', + // version: '0.4.0', // timestamp: new Date().toISOString(), // passwordHash: // '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', @@ -1321,7 +1321,7 @@ export namespace Mock { // startOs: { // 'different-server': { // hostname: 'different-server.local', - // version: '0.3.6', + // version: '0.4.0', // timestamp: new Date().toISOString(), // passwordHash: // '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', @@ -1387,19 +1387,19 @@ export namespace Mock { // ] export const BackupInfo: T.BackupInfo = { - version: '0.3.6', + version: '0.4.0', timestamp: new Date().toISOString(), packageBackups: { bitcoind: { title: 'Bitcoin Core', version: '0.21.0:0', - osVersion: '0.3.6', + osVersion: '0.4.0', timestamp: new Date().toISOString(), }, 'btc-rpc-proxy': { title: 'Bitcoin Proxy', version: '0.2.2:0', - osVersion: '0.3.6', + osVersion: '0.4.0', timestamp: new Date().toISOString(), }, }, diff --git a/web/projects/ui/src/app/services/api/mock-patch.ts b/web/projects/ui/src/app/services/api/mock-patch.ts index 56bb797c9..f9e355dee 100644 --- a/web/projects/ui/src/app/services/api/mock-patch.ts +++ b/web/projects/ui/src/app/services/api/mock-patch.ts @@ -1,6 +1,6 @@ import { DataModel } from 'src/app/services/patch-db/data-model' -import { Mock } from './api.fixures' import { knownAuthorities } from 'src/app/utils/acme' +import { Mock } from './api.fixures' const version = require('../../../../../../package.json').version export const mockPatchData: DataModel = { From 521f61c647955915308a93a0932ab9f96e280565 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Mon, 23 Mar 2026 09:45:16 -0600 Subject: [PATCH 52/53] bump sdk for republish --- sdk/CHANGELOG.md | 2 +- sdk/package/package-lock.json | 4 ++-- sdk/package/package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index ef30ea57c..6066cb4e3 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.4.0-beta.64 (2026-03-22) +## 0.4.0-beta.65 (2026-03-23) ### Added diff --git a/sdk/package/package-lock.json b/sdk/package/package-lock.json index a86d64a29..af061abf1 100644 --- a/sdk/package/package-lock.json +++ b/sdk/package/package-lock.json @@ -1,12 +1,12 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.64", + "version": "0.4.0-beta.65", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.64", + "version": "0.4.0-beta.65", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", diff --git a/sdk/package/package.json b/sdk/package/package.json index 4680a58db..dc8d5b8e1 100644 --- a/sdk/package/package.json +++ b/sdk/package/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/start-sdk", - "version": "0.4.0-beta.64", + "version": "0.4.0-beta.65", "description": "Software development kit to facilitate packaging services for StartOS", "main": "./package/lib/index.js", "types": "./package/lib/index.d.ts", From 19fa1cb4e37f87683741d759e43b15995eaa5061 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 23 Mar 2026 10:12:15 -0600 Subject: [PATCH 53/53] fix build --- core/src/service/effects/subcontainer/sync_dummy.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/service/effects/subcontainer/sync_dummy.rs b/core/src/service/effects/subcontainer/sync_dummy.rs index f7d566394..869cf49fa 100644 --- a/core/src/service/effects/subcontainer/sync_dummy.rs +++ b/core/src/service/effects/subcontainer/sync_dummy.rs @@ -28,3 +28,10 @@ pub fn exec_command(_: ContainerCliContext) -> Result<(), Error> { ErrorKind::InvalidRequest, )) } + +pub fn pipe_wrap(_: ContainerCliContext) -> Result<(), Error> { + Err(Error::new( + eyre!("requires feature container-runtime"), + ErrorKind::InvalidRequest, + )) +}