Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
uses: Swatinem/rust-cache@v2

- name: Install cargo-nextest
run: cargo install cargo-nextest
run: cargo install cargo-nextest --locked

- name: Cache
uses: actions/cache@v4
Expand All @@ -94,4 +94,4 @@ jobs:
run: cargo build --release

- name: Run cargo test regular features
run: cargo nextest run --release
run: cargo nextest run --release --no-tests=warn
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "khost"
version = "0.4.0"
version = "0.5.0"
edition = "2021"
authors = ["Kaspa developers"]
license = "MIT OR Apache-2.0"
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Kaspa p2p node deployment automation tool for Linux.

kHOST was created to automate deployment of Kaspa nodes intended for use as a part of the Kaspa public RPC network as well as private network high-availability clusters. kHOST deploys Rusty-Kaspa nodes from sources, configures them to run as a `systemd` service as well as configures NGINX to act as a reverse proxy for the RPC. This tool exists to simplify and automate Kaspa node deployment as well as to standardize related system configuration.
kHOST was created to automate deployment of Kaspa nodes intended for use as a part of the Kaspa public RPC network as well as private network high-availability clusters. kHOST deploys Rusty-Kaspa nodes from sources, configures them to run as a `systemd` service as well as configures NGINX to act as a reverse proxy for the RPC. This tool exists to simplify and automate Kaspa node deployment as well as to standardize related system configuration.

## Deploying

Expand Down Expand Up @@ -33,3 +33,7 @@ If you already have an existing user and rust installed, you can simply run `car
Please note that the user needs to have root (sudo) privileges to run khost.

IMPORTANT: This tool creates it's own configuration for the kaspad node, as such, any previous configurations should be disabled and removed. If kaspad was running before under the same username, the `~/.rusty-kaspa` data folders containing databases will be re-used.

## Kaspad Default Origins

They are set to `aspectron/*` origins, manually updated from `upstream`. This is a design choice that allows high velocity update coordination and controlled versioning, in practice, it should follow upstream release cycle.
7 changes: 6 additions & 1 deletion src/actions/advanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ impl Action for Advanced {
match selector.interact() {
Ok(BranchChange::Kaspad) => {
let origin = git::create_origin("rusty-kaspa")?;
for config in ctx.config.kaspad.iter_mut() {
for config in ctx
.config
.kaspad
.iter_mut()
.filter(|config| config.network().is_supported())
{
config.set_origin(origin.clone());
}
ctx.config.save()?;
Expand Down
2 changes: 1 addition & 1 deletion src/actions/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl Action for Bootstrap {
resolver::init_resolver_config(ctx).ok();
}

kaspad::select_networks(ctx)?;
kaspad::select_supported_networks(ctx)?;

base::install(ctx, false)?;
ctx.config.bootstrap = true;
Expand Down
94 changes: 82 additions & 12 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::imports::*;

const CONFIG_VERSION: u64 = 2;
const CONFIG_VERSION: u64 = 3;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
Expand All @@ -23,9 +23,18 @@ impl Config {
.with_stats()
.with_local_interface(8989);

let origin = Origin::try_new("https://github.com/aspectron/rusty-kaspa", Some("pnn-v1"))?;
let kaspad = Network::into_iter()
.map(|network| kaspad::Config::new(origin.clone(), network))
let pnnv1_origin = Self::pnnv1_origin()?;
let tn12_origin = Self::pnnv1tn12_origin()?;

let kaspad = SupportedNetwork::iter()
.copied()
.map(|network| {
let selected_origin = match network {
SupportedNetwork::Mainnet | SupportedNetwork::Testnet10 => pnnv1_origin.clone(),
SupportedNetwork::Testnet12 => tn12_origin.clone(),
};
kaspad::Config::new(selected_origin, network.into())
})
.collect::<Vec<_>>();

let nginx = nginx::Config::default();
Expand All @@ -42,6 +51,17 @@ impl Config {
resolver,
})
}

pub fn pnnv1_origin() -> Result<Origin> {
Origin::try_new("https://github.com/aspectron/rusty-kaspa", Some("pnn-v1"))
}

pub fn pnnv1tn12_origin() -> Result<Origin> {
Origin::try_new(
"https://github.com/aspectron/rusty-kaspa",
Some("pnn-v1-tn12"),
)
}
}

impl Config {
Expand All @@ -51,26 +71,64 @@ impl Config {
return Err(Error::custom("Config file not found"));
}
let mut config: Config = serde_json::from_str(&fs::read_to_string(config_path)?)?;
let last_version = config.version;

let mut update = false;
// Migrate old config
if config.version == 1 {
config.kaspad.iter_mut().for_each(|config| {
if let Some(branch) = config.origin_mut().branch_mut() {
if branch == "omega" {
*branch = "pnn-v1".to_string();
update = true;
// v1 -> v2
if last_version <= 1 {
config.kaspad.iter_mut().for_each(|kaspad_config| {
if kaspad_config.network().is_supported() {
if let Some(branch) = kaspad_config.origin_mut().branch_mut() {
if branch == "omega" {
*branch = "pnn-v1".to_string();
update = true;
}
}
}
});
}

// v2 -> v3
if last_version <= 2 {
// push tn12
if !config
.kaspad
.iter()
.any(|config| config.network() == SupportedNetwork::Testnet12.into())
{
config.kaspad.push(kaspad::Config::new(
Self::pnnv1tn12_origin()?,
SupportedNetwork::Testnet12.into(),
));
update = true;
}

// update rk origin
for kaspad_config in config.kaspad.iter_mut().filter(|kaspad_config| {
kaspad_config.is_supported_network()
&& matches!(
kaspad_config.network(),
Network::Supported(SupportedNetwork::Testnet10 | SupportedNetwork::Mainnet)
)
}) {
*kaspad_config.origin_mut() = Self::pnnv1_origin()?;
update = true;
}
}

// keep until v3 is current, gate it to <= 3 on v4
update |= config.remove_unused_legacy_network(DeprecatedNetwork::Testnet11);

if config.version < CONFIG_VERSION {
config.version = CONFIG_VERSION;
update = true;
}

if update {
log::success(format!(
"Updated kHOST config to version {}",
CONFIG_VERSION
))?;
config.version = CONFIG_VERSION;
config.save()?;
}

Expand All @@ -83,6 +141,18 @@ impl Config {
Ok(())
}

/// considered unused if no systemd service and no active in cfg
fn remove_unused_legacy_network(&mut self, network: DeprecatedNetwork) -> bool {
let network = Network::from(network);
let kaspad_len = self.kaspad.len();
self.kaspad.retain(|kaspad_config| {
kaspad_config.network() != network
|| kaspad_config.is_enabled()
|| systemd::is_active(kaspad_config.service_name()).unwrap_or(true)
});
self.kaspad.len() != kaspad_len
}

pub fn reset() {
let path = data_folder().join("config.json");
if let Err(err) = fs::remove_file(&path) {
Expand Down
7 changes: 4 additions & 3 deletions src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,14 @@ where
enum Preset {
PNNv1,
// Delta,
Tn12,
Custom,
}

let preset = if name == "rusty-kaspa" {
cliclack::select(format!("Select git origin for '{name}':"))
.item(Preset::PNNv1, "pnn-v1 (aspectron/pnn-v1)", "")
.item(Preset::Tn12, "tn12 (kaspanet/tn12)", "")
// .item(
// Preset::Delta,
// "Delta",
Expand All @@ -198,9 +200,8 @@ where
};

let origin = match preset {
Preset::PNNv1 => {
Origin::try_new("https://github.com/aspectron/rusty-kaspa", Some("pnn-v1"))?
}
Preset::PNNv1 => Config::pnnv1_origin()?,
Preset::Tn12 => Config::pnnv1tn12_origin()?,
// Preset::Delta => {
// Origin::try_new("https://github.com/aspectron/rusty-kaspa", Some("delta"))?
// }
Expand Down
2 changes: 1 addition & 1 deletion src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub use crate::fqdn;
pub use crate::git::{self, Origin};
pub use crate::kaspad;
pub use crate::khost;
pub use crate::network::{Interface, Network};
pub use crate::network::{DeprecatedNetwork, Interface, Network, SupportedNetwork};
pub use crate::nginx;
pub use crate::nginx::ProxyConfig;
pub use crate::resolver;
Expand Down
Loading
Loading