mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 14:29:45 +00:00
Feature/consolidate setup (#3092)
* start consolidating * add start-cli flash-os * combine install and setup and refactor all * use http * undo mock * fix translation * translations * use dialogservice wrapper * better ST messaging on setup * only warn on update if breakages (#3097) * finish setup wizard and ui language-keyboard feature * fix typo * wip: localization * remove start-tunnel readme * switch to posix strings for language internal * revert mock * translate backend strings * fix missing about text * help text for args * feat: add "Add new gateway" option (#3098) * feat: add "Add new gateway" option * Update web/projects/ui/src/app/routes/portal/components/form/controls/select.component.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * add translation --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Matt Hill <mattnine@protonmail.com> * fix dns selection * keyboard keymap also * ability to shutdown after install * revert mock * working setup flow + manifest localization * (mostly) redundant localization on frontend * version bump * omit live medium from disk list and better space management * ignore missing package archive on 035 migration * fix device migration * add i18n helper to sdk * fix install over 0.3.5.1 * fix grub config --------- Co-authored-by: Matt Hill <mattnine@protonmail.com> Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com> Co-authored-by: Alex Inkin <alexander@inkin.ru> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -20,19 +20,19 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"db",
|
||||
super::db::db_api::<C>()
|
||||
.with_about("Commands to interact with the db i.e. dump and apply"),
|
||||
.with_about("about.commands-interact-with-db-dump-apply"),
|
||||
)
|
||||
.subcommand(
|
||||
"auth",
|
||||
super::auth::auth_api::<C>().with_about("Add or remove authorized clients"),
|
||||
super::auth::auth_api::<C>().with_about("about.add-or-remove-authorized-clients"),
|
||||
)
|
||||
.subcommand(
|
||||
"subnet",
|
||||
subnet_api::<C>().with_about("Add, remove, or modify subnets"),
|
||||
subnet_api::<C>().with_about("about.add-remove-or-modify-subnets"),
|
||||
)
|
||||
.subcommand(
|
||||
"device",
|
||||
device_api::<C>().with_about("Add, remove, or list devices in subnets"),
|
||||
device_api::<C>().with_about("about.add-remove-or-list-devices-in-subnets"),
|
||||
)
|
||||
.subcommand(
|
||||
"port-forward",
|
||||
@@ -42,7 +42,7 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_forward)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a new port forward")
|
||||
.with_about("about.add-new-port-forward")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -50,7 +50,7 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_forward)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a port forward")
|
||||
.with_about("about.remove-port-forward")
|
||||
.with_call_remote::<CliContext>(),
|
||||
),
|
||||
)
|
||||
@@ -70,7 +70,7 @@ pub fn subnet_api<C: Context>() -> ParentHandler<C, SubnetParams> {
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|a, _| a)
|
||||
.no_display()
|
||||
.with_about("Add a new subnet")
|
||||
.with_about("about.add-new-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -79,7 +79,7 @@ pub fn subnet_api<C: Context>() -> ParentHandler<C, SubnetParams> {
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.with_inherited(|a, _| a)
|
||||
.no_display()
|
||||
.with_about("Remove a subnet")
|
||||
.with_about("about.remove-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -91,7 +91,7 @@ pub fn device_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_device)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a device to a subnet")
|
||||
.with_about("about.add-device-to-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -99,7 +99,7 @@ pub fn device_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_device)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove a device from a subnet")
|
||||
.with_about("about.remove-device-from-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -123,13 +123,13 @@ pub fn device_api<C: Context>() -> ParentHandler<C> {
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List devices in a subnet")
|
||||
.with_about("about.list-devices-in-subnet")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"show-config",
|
||||
from_fn_async(show_config)
|
||||
.with_about("Show the WireGuard configuration for a device")
|
||||
.with_about("about.show-wireguard-configuration-for-device")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -129,14 +129,14 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
.subcommand(
|
||||
"set-password",
|
||||
from_fn_async(set_password_cli)
|
||||
.with_about("Set user interface password")
|
||||
.no_display(),
|
||||
.no_display()
|
||||
.with_about("about.set-user-interface-password"),
|
||||
)
|
||||
.subcommand(
|
||||
"reset-password",
|
||||
from_fn_async(reset_password)
|
||||
.with_about("Reset user interface password")
|
||||
.no_display(),
|
||||
.no_display()
|
||||
.with_about("about.reset-user-interface-password"),
|
||||
)
|
||||
.subcommand(
|
||||
"key",
|
||||
@@ -146,7 +146,7 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(add_key)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Add a new authorized key")
|
||||
.with_about("about.add-new-authorized-key")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -154,7 +154,7 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
from_fn_async(remove_key)
|
||||
.with_metadata("sync_db", Value::Bool(true))
|
||||
.no_display()
|
||||
.with_about("Remove an authorized key")
|
||||
.with_about("about.remove-authorized-key")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -175,7 +175,7 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
|
||||
table.print_tty(false)?;
|
||||
Ok(())
|
||||
})
|
||||
.with_about("List authorized keys")
|
||||
.with_about("about.list-authorized-keys")
|
||||
.with_call_remote::<CliContext>(),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -43,11 +43,11 @@ use crate::util::sync::{SyncMutex, Watch};
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[command(rename_all = "kebab-case")]
|
||||
pub struct TunnelConfig {
|
||||
#[arg(short = 'c', long = "config")]
|
||||
#[arg(short = 'c', long = "config", help = "help.arg.config-file-path")]
|
||||
pub config: Option<PathBuf>,
|
||||
#[arg(short = 'l', long = "listen")]
|
||||
#[arg(short = 'l', long = "listen", help = "help.arg.tunnel-listen-address")]
|
||||
pub tunnel_listen: Option<SocketAddr>,
|
||||
#[arg(short = 'd', long = "datadir")]
|
||||
#[arg(short = 'd', long = "datadir", help = "help.arg.data-directory")]
|
||||
pub datadir: Option<PathBuf>,
|
||||
}
|
||||
impl ContextConfig for TunnelConfig {
|
||||
@@ -244,6 +244,7 @@ impl Deref for TunnelContext {
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||
pub struct TunnelAddrParams {
|
||||
#[arg(help = "help.arg.tunnel-ip-address")]
|
||||
pub tunnel: IpAddr,
|
||||
}
|
||||
|
||||
@@ -310,6 +311,7 @@ impl CallRemote<TunnelContext> for CliContext {
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||
pub struct TunnelUrlParams {
|
||||
#[arg(help = "help.arg.tunnel-url")]
|
||||
pub tunnel: Url,
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
|
||||
"dump",
|
||||
from_fn_async(cli_dump)
|
||||
.with_display_serializable()
|
||||
.with_about("Filter/query db to display tables and records"),
|
||||
.with_about("about.filter-query-db-display-tables-records"),
|
||||
)
|
||||
.subcommand(
|
||||
"dump",
|
||||
@@ -107,7 +107,7 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
|
||||
"apply",
|
||||
from_fn_async(cli_apply)
|
||||
.no_display()
|
||||
.with_about("Update a db record"),
|
||||
.with_about("about.update-db-record"),
|
||||
)
|
||||
.subcommand(
|
||||
"apply",
|
||||
@@ -121,8 +121,9 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[command(rename_all = "kebab-case")]
|
||||
pub struct CliDumpParams {
|
||||
#[arg(long = "pointer", short = 'p')]
|
||||
#[arg(long = "pointer", short = 'p', help = "help.arg.json-pointer")]
|
||||
pointer: Option<JsonPointer>,
|
||||
#[arg(help = "help.arg.database-path")]
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@@ -154,7 +155,7 @@ async fn cli_dump(
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[command(rename_all = "kebab-case")]
|
||||
pub struct DumpParams {
|
||||
#[arg(long = "pointer", short = 'p')]
|
||||
#[arg(long = "pointer", short = 'p', help = "help.arg.json-pointer")]
|
||||
#[ts(type = "string | null")]
|
||||
pointer: Option<JsonPointer>,
|
||||
}
|
||||
@@ -170,7 +171,9 @@ pub async fn dump(ctx: TunnelContext, DumpParams { pointer }: DumpParams) -> Res
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[command(rename_all = "kebab-case")]
|
||||
pub struct CliApplyParams {
|
||||
#[arg(help = "help.arg.db-apply-expr")]
|
||||
expr: String,
|
||||
#[arg(help = "help.arg.database-path")]
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@@ -225,7 +228,9 @@ async fn cli_apply(
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[command(rename_all = "kebab-case")]
|
||||
pub struct ApplyParams {
|
||||
#[arg(help = "help.arg.db-apply-expr")]
|
||||
expr: String,
|
||||
#[arg(help = "help.arg.database-path")]
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
|
||||
@@ -98,27 +98,27 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
|
||||
"init",
|
||||
from_fn_async_local(init_web)
|
||||
.no_display()
|
||||
.with_about("Initialize the webserver"),
|
||||
.with_about("about.initialize-webserver"),
|
||||
)
|
||||
.subcommand(
|
||||
"set-listen",
|
||||
from_fn_async(set_listen)
|
||||
.no_display()
|
||||
.with_about("Set the listen address for the webserver")
|
||||
.with_about("about.set-listen-address-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"get-listen",
|
||||
from_fn_async(get_listen)
|
||||
.with_display_serializable()
|
||||
.with_about("Get the listen address for the webserver")
|
||||
.with_about("about.get-listen-address-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"get-available-ips",
|
||||
from_fn_async(get_available_ips)
|
||||
.with_display_serializable()
|
||||
.with_about("Get available IP addresses to bind to")
|
||||
.with_about("about.get-available-ip-addresses-to-bind")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -129,12 +129,12 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
|
||||
"import-certificate",
|
||||
from_fn_async_local(import_certificate_cli)
|
||||
.no_display()
|
||||
.with_about("Import a certificate to use for the webserver"),
|
||||
.with_about("about.import-certificate-for-webserver"),
|
||||
)
|
||||
.subcommand(
|
||||
"generate-certificate",
|
||||
from_fn_async(generate_certificate)
|
||||
.with_about("Generate a certificate to use for the webserver")
|
||||
.with_about("about.generate-certificate-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
@@ -150,28 +150,28 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.with_about("Get the certificate for the webserver")
|
||||
.with_about("about.get-certificate-for-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"enable",
|
||||
from_fn_async(enable_web)
|
||||
.with_about("Enable the webserver")
|
||||
.no_display()
|
||||
.with_about("about.enable-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"disable",
|
||||
from_fn_async(disable_web)
|
||||
.no_display()
|
||||
.with_about("Disable the webserver")
|
||||
.with_about("about.disable-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
.subcommand(
|
||||
"reset",
|
||||
from_fn_async(reset_web)
|
||||
.no_display()
|
||||
.with_about("Reset the webserver")
|
||||
.with_about("about.reset-webserver")
|
||||
.with_call_remote::<CliContext>(),
|
||||
)
|
||||
}
|
||||
@@ -279,7 +279,7 @@ pub async fn import_certificate_cli(
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||
pub struct GenerateCertParams {
|
||||
#[arg(help = "Subject Alternative Name(s)")]
|
||||
#[arg(help = "help.arg.cert-subject-alt-names")]
|
||||
pub subject: Vec<InternedString>,
|
||||
}
|
||||
|
||||
@@ -331,6 +331,7 @@ pub async fn get_certificate(ctx: TunnelContext) -> Result<Option<Pem<Vec<X509>>
|
||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SetListenParams {
|
||||
#[arg(help = "help.arg.listen-address")]
|
||||
pub listen: SocketAddr,
|
||||
}
|
||||
|
||||
@@ -466,7 +467,7 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> {
|
||||
|
||||
println!("✅ Success! ✅");
|
||||
println!(
|
||||
"The webserver is running. Below is your URL{} and Root Certificate Authority (Root CA).",
|
||||
"StartTunnel installed successfully. Below is your Web URL{} and Root Certificate Authority (Root CA).",
|
||||
if password.is_some() {
|
||||
", password,"
|
||||
} else {
|
||||
@@ -474,7 +475,7 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> {
|
||||
}
|
||||
);
|
||||
println!();
|
||||
println!("🌐 URL");
|
||||
println!("🌐 Web URL");
|
||||
println!("https://{listen}");
|
||||
if listen.ip().is_unspecified() {
|
||||
println!(concat!(
|
||||
@@ -517,21 +518,32 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> {
|
||||
.map(Pem)
|
||||
.or_not_found("certificate in chain")?;
|
||||
println!("📝 Root CA:");
|
||||
print!("{cert}");
|
||||
print!("{cert}\n");
|
||||
|
||||
println!(concat!(
|
||||
"To trust your StartTunnel Root CA (above):\n",
|
||||
" 1. Copy the Root CA ",
|
||||
"(starting with -----BEGIN CERTIFICATE----- and ending with -----END CERTIFICATE-----).\n",
|
||||
" 2. Open a text editor: \n",
|
||||
" - Linux: gedit, nano, or any editor\n",
|
||||
" - Mac: TextEdit\n",
|
||||
" - Windows: Notepad\n",
|
||||
" 3. Paste the contents of your Root CA.\n",
|
||||
" 4. Save the file with a `.crt` extension ",
|
||||
"(e.g. `start-tunnel.crt`) (make sure it saves as plain text, not rich text).\n",
|
||||
" 5. Follow instructions to trust you StartTunnel Root CA: ",
|
||||
"https://staging.docs.start9.com/user-manual/trust-ca.html#2-trust-your-servers-root-ca."
|
||||
"To access your Web URL securely, trust your Root CA (displayed above) on your client device(s):\n",
|
||||
" - MacOS\n",
|
||||
" 1. Open the Terminal app\n",
|
||||
" 2. Paste the following command (**DO NOTt** click Return): pbcopy < ~/Desktop/ca.crt\n",
|
||||
" 3. Copy your Root CA (including -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----)\n",
|
||||
" 4. Back in Terminal, click Return. ca.crt is saved to your Desktop\n",
|
||||
" 5. Complete by trusting your Root CA: https://https://staging.docs.start9.com/device-guides/mac/ca.html\n",
|
||||
" - Linux\n",
|
||||
" 1. Open gedit, nano, or any editor\n",
|
||||
" 2. Copy/paste your Root CA (including -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----)\n",
|
||||
" 3. Name the file ca.crt and save as plaintext\n",
|
||||
" 5. Complete by trusting your Root CA: https://https://staging.docs.start9.com/device-guides/linux/ca.html\n",
|
||||
" - Windows\n",
|
||||
" 1. Open the Notepad app\n",
|
||||
" 2. Copy/paste your Root CA (including -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----)\n",
|
||||
" 3. Name the file ca.crt and save as plaintext\n",
|
||||
" 5. Complete by trusting your Root CA: https://https://staging.docs.start9.com/device-guides/windows/ca.html\n",
|
||||
" - Android/Graphene\n",
|
||||
" 1. Send the ca.crt file (created above) to yourself\n",
|
||||
" 2. Complete by trusting your Root CA: https://https://staging.docs.start9.com/device-guides/android/ca.html\n",
|
||||
" - iOS\n",
|
||||
" 1. Send the ca.crt file (created above) to yourself\n",
|
||||
" 2. Complete by trusting your Root CA: https://https://staging.docs.start9.com/device-guides/ios/ca.html\n",
|
||||
));
|
||||
|
||||
return Ok(());
|
||||
|
||||
@@ -41,6 +41,7 @@ impl WgServer {
|
||||
Command::new("wg-quick")
|
||||
.arg("down")
|
||||
.arg(WIREGUARD_INTERFACE_NAME)
|
||||
.env("LANG", "C.UTF-8")
|
||||
.invoke(ErrorKind::Network)
|
||||
.await
|
||||
.or_else(|e| {
|
||||
|
||||
Reference in New Issue
Block a user