mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
enabling support for wireguard and firewall (#2713)
* wip: enabling support for wireguard and firewall * wip * wip * wip * wip * wip * implement some things * fix warning * wip * alpha.23 * misc fixes * remove ufw since no longer required * remove debug info * add cli bindings * debugging * fixes * individualized acme and privacy settings for domains and bindings * sdk version bump * migration * misc fixes * refactor Host::update * debug info * refactor webserver * misc fixes * misc fixes * refactor port forwarding * recheck interfaces every 5 min if no dbus event * misc fixes and cleanup * misc fixes
This commit is contained in:
@@ -294,7 +294,7 @@ impl CallbackHandler {
|
||||
}
|
||||
}
|
||||
pub async fn call(mut self, args: Vector<Value>) -> Result<(), Error> {
|
||||
dbg!(eyre!("callback fired: {}", self.handle.is_active()));
|
||||
crate::dbg!(eyre!("callback fired: {}", self.handle.is_active()));
|
||||
if let Some(seed) = self.seed.upgrade() {
|
||||
seed.persistent_container
|
||||
.callback(self.handle.take(), args)
|
||||
|
||||
@@ -17,11 +17,11 @@ use crate::db::model::package::{
|
||||
use crate::disk::mount::filesystem::bind::Bind;
|
||||
use crate::disk::mount::filesystem::idmapped::IdMapped;
|
||||
use crate::disk::mount::filesystem::{FileSystem, MountType};
|
||||
use crate::rpc_continuations::Guid;
|
||||
use crate::service::effects::prelude::*;
|
||||
use crate::status::health_check::NamedHealthCheckResult;
|
||||
use crate::util::Invoke;
|
||||
use crate::volume::data_dir;
|
||||
use crate::DATA_DIR;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
#[ts(export)]
|
||||
@@ -55,7 +55,7 @@ pub async fn mount(
|
||||
let context = context.deref()?;
|
||||
let subpath = subpath.unwrap_or_default();
|
||||
let subpath = subpath.strip_prefix("/").unwrap_or(&subpath);
|
||||
let source = data_dir(&context.seed.ctx.datadir, &package_id, &volume_id).join(subpath);
|
||||
let source = data_dir(DATA_DIR, &package_id, &volume_id).join(subpath);
|
||||
if tokio::fs::metadata(&source).await.is_err() {
|
||||
tokio::fs::create_dir_all(&source).await?;
|
||||
}
|
||||
|
||||
@@ -130,10 +130,6 @@ pub fn handler<C: Context>() -> ParentHandler<C> {
|
||||
"get-host-info",
|
||||
from_fn_async(net::host::get_host_info).no_cli(),
|
||||
)
|
||||
.subcommand(
|
||||
"get-primary-url",
|
||||
from_fn_async(net::host::get_primary_url).no_cli(),
|
||||
)
|
||||
.subcommand(
|
||||
"get-container-ip",
|
||||
from_fn_async(net::info::get_container_ip).no_cli(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use models::{HostId, PackageId};
|
||||
|
||||
use crate::net::host::binding::{BindId, BindOptions, LanInfo};
|
||||
use crate::net::host::binding::{BindId, BindOptions, NetInfo};
|
||||
use crate::net::host::HostKind;
|
||||
use crate::service::effects::prelude::*;
|
||||
|
||||
@@ -53,15 +53,36 @@ pub struct GetServicePortForwardParams {
|
||||
#[ts(optional)]
|
||||
package_id: Option<PackageId>,
|
||||
host_id: HostId,
|
||||
internal_port: u32,
|
||||
internal_port: u16,
|
||||
}
|
||||
pub async fn get_service_port_forward(
|
||||
context: EffectContext,
|
||||
data: GetServicePortForwardParams,
|
||||
) -> Result<LanInfo, Error> {
|
||||
let internal_port = data.internal_port as u16;
|
||||
|
||||
GetServicePortForwardParams {
|
||||
package_id,
|
||||
host_id,
|
||||
internal_port,
|
||||
}: GetServicePortForwardParams,
|
||||
) -> Result<NetInfo, Error> {
|
||||
let context = context.deref()?;
|
||||
let net_service = context.seed.persistent_container.net_service.lock().await;
|
||||
net_service.get_lan_port(data.host_id, internal_port)
|
||||
|
||||
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
||||
|
||||
Ok(context
|
||||
.seed
|
||||
.ctx
|
||||
.db
|
||||
.peek()
|
||||
.await
|
||||
.as_public()
|
||||
.as_package_data()
|
||||
.as_idx(&package_id)
|
||||
.or_not_found(&package_id)?
|
||||
.as_hosts()
|
||||
.as_idx(&host_id)
|
||||
.or_not_found(&host_id)?
|
||||
.as_bindings()
|
||||
.de()?
|
||||
.get(&internal_port)
|
||||
.or_not_found(lazy_format!("binding for port {internal_port}"))?
|
||||
.net)
|
||||
}
|
||||
|
||||
@@ -1,35 +1,10 @@
|
||||
use models::{HostId, PackageId};
|
||||
|
||||
use crate::net::host::address::HostAddress;
|
||||
use crate::net::host::Host;
|
||||
use crate::service::effects::callbacks::CallbackHandler;
|
||||
use crate::service::effects::prelude::*;
|
||||
use crate::service::rpc::CallbackId;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetPrimaryUrlParams {
|
||||
#[ts(optional)]
|
||||
package_id: Option<PackageId>,
|
||||
host_id: HostId,
|
||||
#[ts(optional)]
|
||||
callback: Option<CallbackId>,
|
||||
}
|
||||
pub async fn get_primary_url(
|
||||
context: EffectContext,
|
||||
GetPrimaryUrlParams {
|
||||
package_id,
|
||||
host_id,
|
||||
callback,
|
||||
}: GetPrimaryUrlParams,
|
||||
) -> Result<Option<HostAddress>, Error> {
|
||||
let context = context.deref()?;
|
||||
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
||||
|
||||
Ok(None) // TODO
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
|
||||
@@ -15,7 +15,6 @@ pub struct ExportServiceInterfaceParams {
|
||||
id: ServiceInterfaceId,
|
||||
name: String,
|
||||
description: String,
|
||||
has_primary: bool,
|
||||
masked: bool,
|
||||
address_info: AddressInfo,
|
||||
r#type: ServiceInterfaceType,
|
||||
@@ -26,7 +25,6 @@ pub async fn export_service_interface(
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
has_primary,
|
||||
masked,
|
||||
address_info,
|
||||
r#type,
|
||||
@@ -39,7 +37,6 @@ pub async fn export_service_interface(
|
||||
id: id.clone(),
|
||||
name,
|
||||
description,
|
||||
has_primary,
|
||||
masked,
|
||||
address_info,
|
||||
interface_type: r#type,
|
||||
|
||||
@@ -51,10 +51,16 @@ pub async fn get_ssl_certificate(
|
||||
.iter()
|
||||
.map(|(_, m)| m.as_hosts().as_entries())
|
||||
.flatten_ok()
|
||||
.map_ok(|(_, m)| m.as_addresses().de())
|
||||
.map_ok(|(_, m)| {
|
||||
Ok(m.as_onions()
|
||||
.de()?
|
||||
.iter()
|
||||
.map(InternedString::from_display)
|
||||
.chain(m.as_domains().keys()?)
|
||||
.collect::<Vec<_>>())
|
||||
})
|
||||
.map(|a| a.and_then(|a| a))
|
||||
.flatten_ok()
|
||||
.map_ok(|a| InternedString::from_display(&a))
|
||||
.try_collect::<_, BTreeSet<_>, _>()?;
|
||||
for hostname in &hostnames {
|
||||
if let Some(internal) = hostname
|
||||
@@ -135,10 +141,16 @@ pub async fn get_ssl_key(
|
||||
.into_iter()
|
||||
.map(|m| m.as_hosts().as_entries())
|
||||
.flatten_ok()
|
||||
.map_ok(|(_, m)| m.as_addresses().de())
|
||||
.map_ok(|(_, m)| {
|
||||
Ok(m.as_onions()
|
||||
.de()?
|
||||
.iter()
|
||||
.map(InternedString::from_display)
|
||||
.chain(m.as_domains().keys()?)
|
||||
.collect::<Vec<_>>())
|
||||
})
|
||||
.map(|a| a.and_then(|a| a))
|
||||
.flatten_ok()
|
||||
.map_ok(|a| InternedString::from_display(&a))
|
||||
.try_collect::<_, BTreeSet<_>, _>()?;
|
||||
for hostname in &hostnames {
|
||||
if let Some(internal) = hostname
|
||||
|
||||
@@ -26,7 +26,7 @@ pub async fn get_store(
|
||||
callback,
|
||||
}: GetStoreParams,
|
||||
) -> Result<Value, Error> {
|
||||
dbg!(&callback);
|
||||
crate::dbg!(&callback);
|
||||
let context = context.deref()?;
|
||||
let peeked = context.seed.ctx.db.peek().await;
|
||||
let package_id = package_id.unwrap_or(context.seed.id.clone());
|
||||
|
||||
@@ -48,7 +48,7 @@ use crate::util::net::WebSocketExt;
|
||||
use crate::util::serde::{NoOutput, Pem};
|
||||
use crate::util::Never;
|
||||
use crate::volume::data_dir;
|
||||
use crate::CAP_1_KiB;
|
||||
use crate::{CAP_1_KiB, DATA_DIR, PACKAGE_DATA};
|
||||
|
||||
pub mod action;
|
||||
pub mod cli;
|
||||
@@ -149,10 +149,10 @@ impl ServiceRef {
|
||||
.values()
|
||||
.flat_map(|h| h.bindings.values())
|
||||
.flat_map(|b| {
|
||||
b.lan
|
||||
b.net
|
||||
.assigned_port
|
||||
.into_iter()
|
||||
.chain(b.lan.assigned_ssl_port)
|
||||
.chain(b.net.assigned_ssl_port)
|
||||
}),
|
||||
);
|
||||
Ok(())
|
||||
@@ -167,17 +167,18 @@ impl ServiceRef {
|
||||
{
|
||||
let state = pde.state_info.expect_removing()?;
|
||||
for volume_id in &state.manifest.volumes {
|
||||
let path = data_dir(&ctx.datadir, &state.manifest.id, volume_id);
|
||||
let path = data_dir(DATA_DIR, &state.manifest.id, volume_id);
|
||||
if tokio::fs::metadata(&path).await.is_ok() {
|
||||
tokio::fs::remove_dir_all(&path).await?;
|
||||
}
|
||||
}
|
||||
let logs_dir = ctx.datadir.join("logs").join(&state.manifest.id);
|
||||
let logs_dir = Path::new(PACKAGE_DATA)
|
||||
.join("logs")
|
||||
.join(&state.manifest.id);
|
||||
if tokio::fs::metadata(&logs_dir).await.is_ok() {
|
||||
tokio::fs::remove_dir_all(&logs_dir).await?;
|
||||
}
|
||||
let archive_path = ctx
|
||||
.datadir
|
||||
let archive_path = Path::new(PACKAGE_DATA)
|
||||
.join("archive")
|
||||
.join("installed")
|
||||
.join(&state.manifest.id);
|
||||
@@ -278,7 +279,7 @@ impl Service {
|
||||
let ctx = ctx.clone();
|
||||
move |s9pk: S9pk, i: Model<PackageDataEntry>| async move {
|
||||
for volume_id in &s9pk.as_manifest().volumes {
|
||||
let path = data_dir(&ctx.datadir, &s9pk.as_manifest().id, volume_id);
|
||||
let path = data_dir(DATA_DIR, &s9pk.as_manifest().id, volume_id);
|
||||
if tokio::fs::metadata(&path).await.is_err() {
|
||||
tokio::fs::create_dir_all(&path).await?;
|
||||
}
|
||||
@@ -291,7 +292,7 @@ impl Service {
|
||||
Self::new(ctx, s9pk, start_stop).await.map(Some)
|
||||
}
|
||||
};
|
||||
let s9pk_dir = ctx.datadir.join(PKG_ARCHIVE_DIR).join("installed"); // TODO: make this based on hash
|
||||
let s9pk_dir = Path::new(DATA_DIR).join(PKG_ARCHIVE_DIR).join("installed"); // TODO: make this based on hash
|
||||
let s9pk_path = s9pk_dir.join(id).with_extension("s9pk");
|
||||
let Some(entry) = ctx
|
||||
.db
|
||||
@@ -605,6 +606,7 @@ impl Service {
|
||||
}
|
||||
|
||||
pub async fn update_host(&self, host_id: HostId) -> Result<(), Error> {
|
||||
let mut service = self.seed.persistent_container.net_service.lock().await;
|
||||
let host = self
|
||||
.seed
|
||||
.ctx
|
||||
@@ -619,13 +621,7 @@ impl Service {
|
||||
.as_idx(&host_id)
|
||||
.or_not_found(&host_id)?
|
||||
.de()?;
|
||||
self.seed
|
||||
.persistent_container
|
||||
.net_service
|
||||
.lock()
|
||||
.await
|
||||
.update(host_id, host)
|
||||
.await
|
||||
service.update(host_id, host).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,7 +930,6 @@ pub async fn attach(
|
||||
.with_kind(ErrorKind::Network)?;
|
||||
current_out = "stdout";
|
||||
}
|
||||
dbg!(¤t_out);
|
||||
ws.send(Message::Binary(out))
|
||||
.await
|
||||
.with_kind(ErrorKind::Network)?;
|
||||
@@ -948,7 +943,6 @@ pub async fn attach(
|
||||
.with_kind(ErrorKind::Network)?;
|
||||
current_out = "stderr";
|
||||
}
|
||||
dbg!(¤t_out);
|
||||
ws.send(Message::Binary(err))
|
||||
.await
|
||||
.with_kind(ErrorKind::Network)?;
|
||||
|
||||
@@ -39,7 +39,7 @@ use crate::util::io::create_file;
|
||||
use crate::util::rpc_client::UnixRpcClient;
|
||||
use crate::util::Invoke;
|
||||
use crate::volume::data_dir;
|
||||
use crate::ARCH;
|
||||
use crate::{ARCH, DATA_DIR, PACKAGE_DATA};
|
||||
|
||||
const RPC_CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
@@ -121,8 +121,8 @@ impl PersistentContainer {
|
||||
.lxc_manager
|
||||
.create(
|
||||
Some(
|
||||
&ctx.datadir
|
||||
.join("package-data/logs")
|
||||
&Path::new(PACKAGE_DATA)
|
||||
.join("logs")
|
||||
.join(&s9pk.as_manifest().id),
|
||||
),
|
||||
LxcConfig::default(),
|
||||
@@ -157,7 +157,7 @@ impl PersistentContainer {
|
||||
.await?;
|
||||
let mount = MountGuard::mount(
|
||||
&IdMapped::new(
|
||||
Bind::new(data_dir(&ctx.datadir, &s9pk.as_manifest().id, volume)),
|
||||
Bind::new(data_dir(DATA_DIR, &s9pk.as_manifest().id, volume)),
|
||||
0,
|
||||
100000,
|
||||
65536,
|
||||
@@ -452,7 +452,7 @@ impl PersistentContainer {
|
||||
#[instrument(skip_all)]
|
||||
pub async fn exit(mut self) -> Result<(), Error> {
|
||||
if let Some(destroy) = self.destroy(false) {
|
||||
dbg!(destroy.await)?;
|
||||
destroy.await?;
|
||||
}
|
||||
tracing::info!("Service for {} exited", self.s9pk.as_manifest().id);
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ impl serde::Serialize for Sandbox {
|
||||
pub struct CallbackId(u64);
|
||||
impl CallbackId {
|
||||
pub fn register(self, container: &PersistentContainer) -> CallbackHandle {
|
||||
dbg!(eyre!(
|
||||
crate::dbg!(eyre!(
|
||||
"callback {} registered for {}",
|
||||
self.0,
|
||||
container.s9pk.as_manifest().id
|
||||
|
||||
@@ -36,7 +36,41 @@ impl Actor for ServiceActor {
|
||||
ServiceActorLoopNext::DontWait => (),
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
let seed = self.0.clone();
|
||||
let mut ip_info = seed.ctx.net_controller.net_iface.subscribe();
|
||||
jobs.add_job(async move {
|
||||
loop {
|
||||
if let Err(e) = async {
|
||||
let mut service = seed.persistent_container.net_service.lock().await;
|
||||
let hosts = seed
|
||||
.ctx
|
||||
.db
|
||||
.peek()
|
||||
.await
|
||||
.as_public()
|
||||
.as_package_data()
|
||||
.as_idx(&seed.id)
|
||||
.or_not_found(&seed.id)?
|
||||
.as_hosts()
|
||||
.de()?;
|
||||
for (host_id, host) in hosts.0 {
|
||||
service.update(host_id, host).await?;
|
||||
}
|
||||
|
||||
Ok::<_, Error>(())
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error syncronizing net host after network change: {e}");
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
|
||||
if ip_info.changed().await.is_err() {
|
||||
break;
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +126,6 @@ async fn service_actor_loop(
|
||||
..
|
||||
} => MainStatus::Stopped,
|
||||
};
|
||||
let previous = i.as_status().de()?;
|
||||
i.as_status_mut().ser(&main_status)?;
|
||||
return Ok(previous
|
||||
.major_changes(&main_status)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -27,6 +28,7 @@ use crate::service::start_stop::StartStop;
|
||||
use crate::service::{LoadDisposition, Service, ServiceRef};
|
||||
use crate::status::MainStatus;
|
||||
use crate::util::serde::Pem;
|
||||
use crate::DATA_DIR;
|
||||
|
||||
pub type DownloadInstallFuture = BoxFuture<'static, Result<InstallFuture, Error>>;
|
||||
pub type InstallFuture = BoxFuture<'static, Result<(), Error>>;
|
||||
@@ -220,8 +222,7 @@ impl ServiceMap {
|
||||
Ok(async move {
|
||||
let (installed_path, sync_progress_task) = reload_guard
|
||||
.handle(async {
|
||||
let download_path = ctx
|
||||
.datadir
|
||||
let download_path = Path::new(DATA_DIR)
|
||||
.join(PKG_ARCHIVE_DIR)
|
||||
.join("downloading")
|
||||
.join(&id)
|
||||
@@ -251,8 +252,7 @@ impl ServiceMap {
|
||||
file.sync_all().await?;
|
||||
download_progress.complete();
|
||||
|
||||
let installed_path = ctx
|
||||
.datadir
|
||||
let installed_path = Path::new(DATA_DIR)
|
||||
.join(PKG_ARCHIVE_DIR)
|
||||
.join("installed")
|
||||
.join(&id)
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::service::ServiceActor;
|
||||
use crate::util::actor::background::BackgroundJobQueue;
|
||||
use crate::util::actor::{ConflictBuilder, Handler};
|
||||
use crate::util::future::RemoteCancellable;
|
||||
use crate::util::serde::NoOutput;
|
||||
|
||||
pub(in crate::service) struct Backup {
|
||||
pub path: PathBuf,
|
||||
@@ -48,7 +49,7 @@ impl Handler<Backup> for ServiceActor {
|
||||
.mount_backup(path, ReadWrite)
|
||||
.await?;
|
||||
seed.persistent_container
|
||||
.execute(id, ProcedureName::CreateBackup, Value::Null, None)
|
||||
.execute::<NoOutput>(id, ProcedureName::CreateBackup, Value::Null, None)
|
||||
.await?;
|
||||
backup_guard.unmount(true).await?;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::service::ServiceActor;
|
||||
use crate::util::actor::background::BackgroundJobQueue;
|
||||
use crate::util::actor::{ConflictBuilder, Handler};
|
||||
use crate::util::future::RemoteCancellable;
|
||||
use crate::util::serde::NoOutput;
|
||||
|
||||
pub(in crate::service) struct Restore {
|
||||
pub path: PathBuf,
|
||||
@@ -38,7 +39,7 @@ impl Handler<Restore> for ServiceActor {
|
||||
.mount_backup(path, ReadOnly)
|
||||
.await?;
|
||||
seed.persistent_container
|
||||
.execute(id, ProcedureName::RestoreBackup, Value::Null, None)
|
||||
.execute::<NoOutput>(id, ProcedureName::RestoreBackup, Value::Null, None)
|
||||
.await?;
|
||||
backup_guard.unmount(true).await?;
|
||||
|
||||
@@ -48,7 +49,7 @@ impl Handler<Restore> for ServiceActor {
|
||||
Ok::<_, Error>(())
|
||||
}
|
||||
.map(|x| {
|
||||
if let Err(err) = dbg!(x) {
|
||||
if let Err(err) = x {
|
||||
tracing::debug!("{:?}", err);
|
||||
tracing::warn!("{}", err);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user