persist hostname in config overlay (#2769)

* persist hostname

* add migration

* fix version mismatch

* remove dmesg logging from build
This commit is contained in:
Aiden McClelland
2024-10-30 12:55:36 -06:00
committed by GitHub
parent 480f5c1a9a
commit 2091abeea2
17 changed files with 105 additions and 73 deletions

View File

@@ -213,7 +213,7 @@ emulate-reflash: $(ALL_TARGETS)
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
$(call ssh,'sudo /usr/lib/startos/scripts/chroot-and-upgrade --create')
$(MAKE) install REMOTE=$(REMOTE) SSHPASS=$(SSHPASS) DESTDIR=/media/startos/next PLATFORM=$(PLATFORM)
$(call ssh,'sudo rm -f /media/startos/config/disk.guid')
$(call ssh,'sudo rm -f /media/startos/config/disk.guid /media/startos/config/overlay/etc/hostname')
$(call ssh,'sudo /media/startos/next/usr/lib/startos/scripts/chroot-and-upgrade --no-sync "apt-get install -y $(shell cat ./build/lib/depends)"')
upload-ota: results/$(BASENAME).squashfs

2
core/Cargo.lock generated
View File

@@ -5051,7 +5051,7 @@ dependencies = [
[[package]]
name = "start-os"
version = "0.3.6-alpha.6"
version = "0.3.6-alpha.7"
dependencies = [
"aes",
"async-compression",

View File

@@ -14,7 +14,7 @@ keywords = [
name = "start-os"
readme = "README.md"
repository = "https://github.com/Start9Labs/start-os"
version = "0.3.6-alpha.6"
version = "0.3.6-alpha.7"
license = "MIT"
[lib]

View File

@@ -21,6 +21,7 @@ use crate::account::AccountInfo;
use crate::context::config::ServerConfig;
use crate::context::RpcContext;
use crate::disk::OsPartitionInfo;
use crate::hostname::Hostname;
use crate::init::init_postgres;
use crate::prelude::*;
use crate::progress::FullProgressTracker;
@@ -42,6 +43,8 @@ lazy_static::lazy_static! {
pub struct SetupResult {
pub tor_address: String,
#[ts(type = "string")]
pub hostname: Hostname,
#[ts(type = "string")]
pub lan_address: InternedString,
pub root_ca: String,
}
@@ -50,6 +53,7 @@ impl TryFrom<&AccountInfo> for SetupResult {
fn try_from(value: &AccountInfo) -> Result<Self, Self::Error> {
Ok(Self {
tor_address: format!("https://{}", value.tor_key.public().get_onion_address()),
hostname: value.hostname.clone(),
lan_address: value.hostname.lan_address(),
root_ca: String::from_utf8(value.root_ca_cert.to_pem()?)?,
})

View File

@@ -9,6 +9,7 @@ use rpc_toolkit::{
use crate::context::{CliContext, DiagnosticContext, RpcContext};
use crate::init::SYSTEM_REBUILD_PATH;
use crate::shutdown::Shutdown;
use crate::util::io::delete_file;
use crate::Error;
pub fn diagnostic<C: Context>() -> ParentHandler<C> {
@@ -95,9 +96,7 @@ pub fn disk<C: Context>() -> ParentHandler<C> {
}
pub async fn forget_disk<C: Context>(_: C) -> Result<(), Error> {
let disk_guid = Path::new("/media/startos/config/disk.guid");
if tokio::fs::metadata(disk_guid).await.is_ok() {
tokio::fs::remove_file(disk_guid).await?;
}
delete_file("/media/startos/config/overlay/etc/hostname").await?;
delete_file("/media/startos/config/disk.guid").await?;
Ok(())
}

View File

@@ -21,7 +21,7 @@ use crate::disk::OsPartitionInfo;
use crate::net::utils::find_eth_iface;
use crate::prelude::*;
use crate::s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile;
use crate::util::io::{open_file, TmpDir};
use crate::util::io::{delete_file, open_file, TmpDir};
use crate::util::serde::IoFormat;
use crate::util::Invoke;
use crate::ARCH;
@@ -180,18 +180,9 @@ pub async fn execute<C: Context>(
{
if let Err(e) = async {
// cp -r ${guard}/config /tmp/config
if tokio::fs::metadata(guard.path().join("config/upgrade"))
.await
.is_ok()
{
tokio::fs::remove_file(guard.path().join("config/upgrade")).await?;
}
if tokio::fs::metadata(guard.path().join("config/disk.guid"))
.await
.is_ok()
{
tokio::fs::remove_file(guard.path().join("config/disk.guid")).await?;
}
delete_file(guard.path().join("config/upgrade")).await?;
delete_file(guard.path().join("config/overlay/etc/hostname")).await?;
delete_file(guard.path().join("config/disk.guid")).await?;
Command::new("cp")
.arg("-r")
.arg(guard.path().join("config"))

View File

@@ -10,6 +10,7 @@ use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize};
use tokio::io::AsyncWriteExt;
use tokio::process::Command;
use tokio::try_join;
use tracing::instrument;
use ts_rs::TS;
@@ -36,6 +37,7 @@ use crate::progress::{FullProgress, PhaseProgressTrackerHandle};
use crate::rpc_continuations::Guid;
use crate::util::crypto::EncryptedWire;
use crate::util::io::{create_file, dir_copy, dir_size, Counter};
use crate::util::Invoke;
use crate::{Error, ErrorKind, ResultExt};
pub fn setup<C: Context>() -> ParentHandler<C> {
@@ -336,6 +338,11 @@ pub async fn complete(ctx: SetupContext) -> Result<SetupResult, Error> {
let mut guid_file = create_file("/media/startos/config/disk.guid").await?;
guid_file.write_all(ctx.disk_guid.as_bytes()).await?;
guid_file.sync_all().await?;
Command::new("systemd-firstboot")
.arg("--root=/media/startos/config/overlay/")
.arg(format!("--hostname={}", res.hostname.0))
.invoke(ErrorKind::ParseSysInfo)
.await?;
Ok(res.clone())
}
Some(Err(e)) => Err(e.clone_output()),

View File

@@ -923,6 +923,20 @@ pub async fn create_file(path: impl AsRef<Path>) -> Result<File, Error> {
.with_ctx(|_| (ErrorKind::Filesystem, lazy_format!("create {path:?}")))
}
pub async fn delete_file(path: impl AsRef<Path>) -> Result<(), Error> {
let path = path.as_ref();
tokio::fs::remove_file(path)
.await
.or_else(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
Ok(())
} else {
Err(e)
}
})
.with_ctx(|_| (ErrorKind::Filesystem, lazy_format!("delete {path:?}")))
}
pub async fn rename(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<(), Error> {
let src = src.as_ref();
let dst = dst.as_ref();

View File

@@ -306,7 +306,10 @@ where
Ok(())
}
/// MUST be idempotent, and is run after *all* db migrations
fn post_up(self, ctx: &RpcContext) -> impl Future<Output = Result<(), Error>> + Send + 'static {
fn post_up<'a>(
self,
ctx: &'a RpcContext,
) -> impl Future<Output = Result<(), Error>> + Send + 'a {
async { Ok(()) }
}
fn down(self, db: &mut Value) -> Result<(), Error> {

View File

@@ -19,6 +19,10 @@ use torut::onion::TorSecretKeyV3;
use super::v0_3_5::V0_3_0_COMPAT;
use super::{v0_3_5_2, VersionT};
use crate::account::AccountInfo;
use crate::auth::Sessions;
use crate::backup::target::cifs::CifsTargets;
use crate::context::RpcContext;
use crate::db::model::Database;
use crate::disk::mount::filesystem::cifs::Cifs;
use crate::disk::mount::util::unmount;
@@ -26,19 +30,15 @@ use crate::hostname::Hostname;
use crate::net::forward::AvailablePorts;
use crate::net::keys::KeyStore;
use crate::net::ssl::CertStore;
use crate::net::tor;
use crate::net::tor::OnionStore;
use crate::notifications::{Notification, Notifications};
use crate::prelude::*;
use crate::s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile;
use crate::ssh::{SshKeys, SshPubKey};
use crate::util::crypto::ed25519_expand_key;
use crate::util::serde::{Pem, PemEncoding};
use crate::util::Invoke;
use crate::{account::AccountInfo, net::tor};
use crate::{auth::Sessions, context::RpcContext};
use crate::{
backup::target::cifs::CifsTargets,
s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile,
};
lazy_static::lazy_static! {
static ref V0_3_6_alpha_0: exver::Version = exver::Version::new(
@@ -328,61 +328,58 @@ impl VersionT for Version {
#[instrument(skip(self, ctx))]
/// MUST be idempotent, and is run after *all* db migrations
fn post_up(self, ctx: &RpcContext) -> impl Future<Output = Result<(), Error>> + Send + 'static {
let ctx = ctx.clone();
async move {
let path = Path::new("/embassy-data/package-data/archive/");
async fn post_up(self, ctx: &RpcContext) -> Result<(), Error> {
let path = Path::new("/embassy-data/package-data/archive/");
if !path.is_dir() {
return Err(Error::new(
eyre!(
"expected path ({}) to be a directory",
path.to_string_lossy()
),
ErrorKind::Filesystem,
));
}
// Should be the name of the package
let mut paths = tokio::fs::read_dir(path).await?;
while let Some(path) = paths.next_entry().await? {
let path = path.path();
if !path.is_dir() {
return Err(Error::new(
eyre!(
"expected path ({}) to be a directory",
path.to_string_lossy()
),
ErrorKind::Filesystem,
));
continue;
}
// Should be the name of the package
// Should be the version of the package
let mut paths = tokio::fs::read_dir(path).await?;
while let Some(path) = paths.next_entry().await? {
let path = path.path();
if !path.is_dir() {
continue;
}
// Should be the version of the package
// Should be s9pk
let mut paths = tokio::fs::read_dir(path).await?;
while let Some(path) = paths.next_entry().await? {
let path = path.path();
if !path.is_dir() {
if path.is_dir() {
continue;
}
// Should be s9pk
let mut paths = tokio::fs::read_dir(path).await?;
while let Some(path) = paths.next_entry().await? {
let path = path.path();
if path.is_dir() {
continue;
}
let package_s9pk = tokio::fs::File::open(path).await?;
let file = MultiCursorFile::open(&package_s9pk).await?;
let package_s9pk = tokio::fs::File::open(path).await?;
let file = MultiCursorFile::open(&package_s9pk).await?;
let key = ctx.db.peek().await.into_private().into_compat_s9pk_key();
ctx.services
.install(
ctx.clone(),
|| crate::s9pk::load(file.clone(), || Ok(key.de()?.0), None),
None::<crate::util::Never>,
None,
)
.await?
.await?
.await?;
}
let key = ctx.db.peek().await.into_private().into_compat_s9pk_key();
ctx.services
.install(
ctx.clone(),
|| crate::s9pk::load(file.clone(), || Ok(key.de()?.0), None),
None::<crate::util::Never>,
None,
)
.await?
.await?
.await?;
}
}
Ok(())
}
Ok(())
}
}

View File

@@ -1,9 +1,11 @@
use exver::{PreReleaseSegment, VersionRange};
use imbl_value::{json, InOMap};
use tokio::process::Command;
use super::v0_3_5::V0_3_0_COMPAT;
use super::{v0_3_6_alpha_6, VersionT};
use crate::prelude::*;
use crate::util::Invoke;
lazy_static::lazy_static! {
static ref V0_3_6_alpha_7: exver::Version = exver::Version::new(
@@ -44,6 +46,17 @@ impl VersionT for Version {
}
Ok(())
}
async fn post_up(self, ctx: &crate::context::RpcContext) -> Result<(), Error> {
Command::new("systemd-firstboot")
.arg("--root=/media/startos/config/overlay/")
.arg(format!(
"--hostname={}",
ctx.account.read().await.hostname.0
))
.invoke(ErrorKind::ParseSysInfo)
.await?;
Ok(())
}
fn down(self, _db: &mut Value) -> Result<(), Error> {
Ok(())
}

View File

@@ -57,13 +57,14 @@ if [ "$NON_FREE" = 1 ]; then
fi
fi
PLATFORM_CONFIG_EXTRAS=
PLATFORM_CONFIG_EXTRAS=()
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --firmware-binary false"
PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --firmware-chroot false"
PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-flavours rpi-v8"
PLATFORM_CONFIG_EXTRAS+=( --firmware-binary false )
PLATFORM_CONFIG_EXTRAS+=( --firmware-chroot false )
PLATFORM_CONFIG_EXTRAS+=( --linux-packages linux-image-6.6.51+rpt )
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours "rpi-v8 rpi-2712" )
elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-flavours rockchip64"
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours rockchip64 )
fi
@@ -87,7 +88,7 @@ lb config \
--bootstrap-qemu-arch ${IB_TARGET_ARCH} \
--bootstrap-qemu-static /usr/bin/qemu-${QEMU_ARCH}-static \
--archive-areas "${ARCHIVE_AREAS}" \
$PLATFORM_CONFIG_EXTRAS
${PLATFORM_CONFIG_EXTRAS[@]}
# Overlays

View File

@@ -2,6 +2,7 @@
export type SetupResult = {
torAddress: string
hostname: string
lanAddress: string
rootCa: string
}

View File

@@ -1,6 +1,6 @@
{
"name": "startos-ui",
"version": "0.3.6-alpha.6",
"version": "0.3.6-alpha.7",
"author": "Start9 Labs, Inc",
"homepage": "https://start9.com/",
"license": "MIT",

View File

@@ -21,5 +21,5 @@
"ackInstructions": {},
"theme": "Dark",
"widgets": [],
"ack-welcome": "0.3.6-alpha.6"
"ack-welcome": "0.3.6-alpha.7"
}

View File

@@ -137,6 +137,7 @@ export class MockApiService extends ApiService {
return {
status: 'complete',
torAddress: 'https://asdafsadasdasasdasdfasdfasdf.onion',
hostname: 'adjective-noun',
lanAddress: 'https://adjective-noun.local',
rootCa: encodeBase64(rootCA),
}
@@ -283,6 +284,7 @@ export class MockApiService extends ApiService {
await pauseFor(1000)
return {
torAddress: 'https://asdafsadasdasasdasdfasdfasdf.onion',
hostname: 'adjective-noun',
lanAddress: 'https://adjective-noun.local',
rootCa: encodeBase64(rootCA),
}

View File

@@ -12,7 +12,7 @@
<ion-content class="ion-padding">
<h2>This Release</h2>
<h4>0.3.6-alpha.6</h4>
<h4>0.3.6-alpha.7</h4>
<h6>This is an ALPHA release! DO NOT use for production data!</h6>
<h6>
Expect that any data you create or store on this version of the OS can be