diff --git a/Cargo.lock b/Cargo.lock index e070b8a03..978f94a0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -287,9 +278,9 @@ dependencies = [ [[package]] name = "aws-sdk-ec2" -version = "1.173.0" +version = "1.175.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daa0257ec1eb83217a286d91f836e7a1f82e885a6c890a8c9ff28a7f8dc71bf" +checksum = "c1515b09ab70c0991c0b002b0e9114a3ee73b7c5d3d65dfdb047278b208f21b0" dependencies = [ "aws-credential-types", "aws-runtime", @@ -449,7 +440,7 @@ dependencies = [ "hyper-util", "pin-project-lite", "rustls 0.21.12", - "rustls 0.23.32", + "rustls 0.23.33", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -680,7 +671,7 @@ dependencies = [ "hyper 1.7.0", "hyper-util", "pin-project-lite", - "rustls 0.23.32", + "rustls 0.23.33", "rustls-pemfile 2.2.0", "rustls-pki-types", "tokio", @@ -688,21 +679,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link 0.2.1", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -885,7 +861,7 @@ dependencies = [ "getrandom 0.2.16", "getrandom 0.3.3", "hex", - "indexmap 2.11.4", + "indexmap 2.12.0", "js-sys", "once_cell", "rand 0.9.2", @@ -1147,7 +1123,7 @@ name = "config" version = "2.0.0-dev-60" dependencies = [ "colored", - "indexmap 2.11.4", + "indexmap 2.12.0", "regex", "serde", "serde_json", @@ -1233,6 +1209,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "croner" version = "3.0.0" @@ -1244,6 +1226,24 @@ dependencies = [ "strum", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -2019,12 +2019,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "git" version = "2.0.0-dev-60" @@ -2067,7 +2061,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.11.4", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -2086,7 +2080,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.11.4", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -2180,6 +2174,31 @@ dependencies = [ "url", ] +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.9.2", + "ring", + "thiserror 2.0.17", + "tinyvec", + "tokio", + "tracing", + "url", +] + [[package]] name = "hickory-resolver" version = "0.24.4" @@ -2188,7 +2207,7 @@ checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" dependencies = [ "cfg-if", "futures-util", - "hickory-proto", + "hickory-proto 0.24.4", "ipconfig", "lru-cache", "once_cell", @@ -2201,6 +2220,27 @@ dependencies = [ "tracing", ] +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto 0.25.2", + "ipconfig", + "moka", + "once_cell", + "parking_lot", + "rand 0.9.2", + "resolv-conf", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -2380,7 +2420,7 @@ dependencies = [ "http 1.3.1", "hyper 1.7.0", "hyper-util", - "rustls 0.23.32", + "rustls 0.23.33", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -2593,9 +2633,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.4" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", "hashbrown 0.16.0", @@ -2621,17 +2661,6 @@ dependencies = [ "svi", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", -] - [[package]] name = "ipconfig" version = "0.3.2" @@ -2785,7 +2814,7 @@ dependencies = [ "derive_variants", "envy", "futures", - "indexmap 2.11.4", + "indexmap 2.12.0", "ipnetwork", "mongo_indexed", "partial_derive2", @@ -2843,7 +2872,7 @@ dependencies = [ "git", "hex", "hmac", - "indexmap 2.11.4", + "indexmap 2.12.0", "interpolate", "jsonwebtoken", "komodo_client", @@ -2856,7 +2885,7 @@ dependencies = [ "reqwest", "resolver_api", "response", - "rustls 0.23.32", + "rustls 0.23.33", "secret_file", "serde", "serde_json", @@ -2905,6 +2934,7 @@ dependencies = [ "formatting", "futures", "git", + "hickory-resolver 0.25.2", "interpolate", "komodo_client", "logger", @@ -2913,7 +2943,7 @@ dependencies = [ "portable-pty", "resolver_api", "run_command", - "rustls 0.23.32", + "rustls 0.23.33", "secret_file", "serde", "serde_json", @@ -3143,6 +3173,24 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "moka" +version = "0.12.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "rustc_version", + "smallvec", + "tagptr", + "uuid", +] + [[package]] name = "mongo_indexed" version = "2.0.2" @@ -3202,8 +3250,8 @@ dependencies = [ "futures-io", "futures-util", "hex", - "hickory-proto", - "hickory-resolver", + "hickory-proto 0.24.4", + "hickory-resolver 0.24.4", "hmac", "macro_magic", "md-5", @@ -3214,7 +3262,7 @@ dependencies = [ "percent-encoding", "rand 0.8.5", "rustc_version_runtime", - "rustls 0.23.32", + "rustls 0.23.33", "rustversion", "serde", "serde_bytes", @@ -3422,20 +3470,15 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "once_cell_polyfill" @@ -3801,6 +3844,12 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "portable-pty" version = "0.9.0" @@ -3909,7 +3958,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.32", + "rustls 0.23.33", "socket2 0.6.1", "thiserror 2.0.17", "tokio", @@ -3929,7 +3978,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.32", + "rustls 0.23.33", "rustls-pki-types", "slab", "thiserror 2.0.17", @@ -4121,7 +4170,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.32", + "rustls 0.23.33", "rustls-native-certs 0.8.1", "rustls-pki-types", "serde", @@ -4232,12 +4281,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -4290,9 +4333,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +checksum = "751e04a496ca00bb97a5e043158d23d66b5aabf2e1d5aa2a0aaebb1aafe6f82c" dependencies = [ "aws-lc-rs", "log", @@ -4558,7 +4601,7 @@ version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "itoa", "memchr", "ryu", @@ -4639,7 +4682,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.4", + "indexmap 2.12.0", "schemars 0.9.0", "schemars 1.0.4", "serde_core", @@ -4666,7 +4709,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "itoa", "ryu", "serde", @@ -4806,9 +4849,9 @@ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "slack_client_rs" -version = "1.2.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295af69963fd1298940a45be3cefa447285f7cd71970f4a47e54be26771a7be6" +checksum = "5e52d695d2a62bb62481567a1fafc9d83af9f2c469fa37872136e0171e6b3936" dependencies = [ "anyhow", "reqwest", @@ -5004,6 +5047,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "take_mut" version = "0.2.2" @@ -5132,29 +5181,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", "socket2 0.6.1", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -5177,7 +5223,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.32", + "rustls 0.23.33", "tokio", ] @@ -5201,7 +5247,7 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "rustls 0.23.32", + "rustls 0.23.33", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -5229,7 +5275,7 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "serde_core", "serde_spanned", "toml_datetime", @@ -5321,7 +5367,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "indexmap 2.11.4", + "indexmap 2.12.0", "pin-project-lite", "slab", "sync_wrapper", @@ -5476,7 +5522,7 @@ dependencies = [ "periphery_client", "pin-project-lite", "rand 0.9.2", - "rustls 0.23.32", + "rustls 0.23.33", "serde", "serror", "sha1", @@ -5507,7 +5553,7 @@ dependencies = [ "httparse", "log", "rand 0.9.2", - "rustls 0.23.32", + "rustls 0.23.33", "rustls-pki-types", "sha1", "thiserror 2.0.17", diff --git a/Cargo.toml b/Cargo.toml index c00e5077f..9d3da068b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ git = { path = "lib/git" } # MOGH run_command = { version = "0.0.6", features = ["async_tokio"] } serror = { version = "0.5.3", default-features = false } -slack = { version = "1.2.1", package = "slack_client_rs", default-features = false, features = ["rustls"] } +slack = { version = "2.0.0", package = "slack_client_rs", default-features = false, features = ["rustls"] } derive_default_builder = "0.1.8" derive_empty_traits = "0.1.0" async_timing_util = "1.1.0" @@ -55,7 +55,7 @@ svi = "1.2.0" # ASYNC reqwest = { version = "0.12.24", default-features = false, features = ["json", "stream", "rustls-tls-native-roots"] } -tokio = { version = "1.47.1", features = ["full"] } +tokio = { version = "1.48.0", features = ["full"] } tokio-util = { version = "0.7.16", features = ["io", "codec"] } tokio-stream = { version = "0.1.17", features = ["sync"] } pin-project-lite = "0.2.16" @@ -72,7 +72,7 @@ axum = { version = "0.8.6", features = ["ws", "json", "macros"] } # SER/DE ipnetwork = { version = "0.21.1", features = ["serde"] } -indexmap = { version = "2.11.4", features = ["serde"] } +indexmap = { version = "2.12.0", features = ["serde"] } serde = { version = "1.0.227", features = ["derive"] } strum = { version = "0.27.2", features = ["derive"] } bson = { version = "2.15.0" } # must keep in sync with mongodb version @@ -103,7 +103,7 @@ envy = "0.4.2" # CRYPTO / AUTH uuid = { version = "1.18.1", features = ["v4", "fast-rng", "serde"] } jsonwebtoken = { version = "10.0.0", features = ["aws_lc_rs"] } # locked back with octorust -rustls = { version = "0.23.32", features = ["aws-lc-rs"] } +rustls = { version = "0.23.33", features = ["aws-lc-rs"] } pem-rfc7468 = { version = "0.7.0", features = ["alloc"] } openidconnect = "4.0.1" urlencoding = "2.1.3" @@ -126,7 +126,7 @@ sysinfo = "0.37.1" # CLOUD aws-config = "1.8.8" -aws-sdk-ec2 = "1.173.0" +aws-sdk-ec2 = "1.175.1" aws-credential-types = "1.2.8" ## CRON @@ -137,6 +137,7 @@ croner = "3.0.0" # MISC async-compression = { version = "0.4.32", features = ["tokio", "gzip"] } +hickory-resolver = "0.25.2" derive_builder = "0.20.2" shell-escape = "0.1.5" comfy-table = "7.2.1" diff --git a/bin/core/src/resource/server.rs b/bin/core/src/resource/server.rs index 823920560..f41598320 100644 --- a/bin/core/src/resource/server.rs +++ b/bin/core/src/resource/server.rs @@ -71,6 +71,7 @@ impl super::KomodoResource for Server { let ( version, public_key, + public_ip, terminals_disabled, container_terminals_disabled, ) = match status.as_ref().and_then(|s| s.periphery_info.as_ref()) @@ -78,10 +79,11 @@ impl super::KomodoResource for Server { Some(info) => ( Some(info.version.clone()), Some(info.public_key.clone()), + info.public_ip.clone(), info.terminals_disabled, info.container_terminals_disabled, ), - None => (None, None, true, true), + None => (None, None, None, true, true), }; ServerListItem { name: server.name, @@ -110,6 +112,7 @@ impl super::KomodoResource for Server { attempted_public_key: optional_string( server.info.attempted_public_key, ), + public_ip, terminals_disabled, container_terminals_disabled, }, diff --git a/bin/periphery/Cargo.toml b/bin/periphery/Cargo.toml index 7a298b61b..c774ab9e6 100644 --- a/bin/periphery/Cargo.toml +++ b/bin/periphery/Cargo.toml @@ -37,6 +37,7 @@ derive_variants.workspace = true resolver_api.workspace = true run_command.workspace = true # external +hickory-resolver.workspace = true serde_yaml_ng.workspace = true tokio-stream.workspace = true portable-pty.workspace = true diff --git a/bin/periphery/src/api/mod.rs b/bin/periphery/src/api/mod.rs index 8febcb03a..aaf9d463c 100644 --- a/bin/periphery/src/api/mod.rs +++ b/bin/periphery/src/api/mod.rs @@ -19,7 +19,9 @@ use uuid::Uuid; use crate::{ api::compose::list_compose_projects, config::periphery_config, - state::{docker_client, periphery_keys, stats_client}, + state::{ + docker_client, host_public_ip, periphery_keys, stats_client, + }, }; pub mod terminal; @@ -240,6 +242,7 @@ impl Resolve for PollStatus { .disable_container_terminals, stats_polling_rate: config.stats_polling_rate, docker_connected: docker_client().load().is_some(), + public_ip: host_public_ip().await.cloned(), }, system_info: stats_client.info.clone(), system_stats, diff --git a/bin/periphery/src/helpers.rs b/bin/periphery/src/helpers.rs index d0df24ae7..30aed3fe9 100644 --- a/bin/periphery/src/helpers.rs +++ b/bin/periphery/src/helpers.rs @@ -1,4 +1,6 @@ -use std::path::PathBuf; +use std::{ + net::IpAddr, path::PathBuf, str::FromStr as _, sync::OnceLock, +}; use anyhow::Context; use command::run_komodo_command_with_sanitization; @@ -204,6 +206,57 @@ pub fn registry_token( .with_context(|| format!("did not find token in config for docker registry account {account_username} | domain {domain}")) } +// ==================== +// Public IP over DNS +// ==================== + +type OpenDNSResolver = hickory_resolver::Resolver< + hickory_resolver::name_server::TokioConnectionProvider, +>; + +fn opendns_resolver() -> &'static OpenDNSResolver { + static OPENDNS_RESOLVER: OnceLock = + OnceLock::new(); + OPENDNS_RESOLVER.get_or_init(|| { + // OpenDNS resolver ips + let ips = [ + IpAddr::from_str("208.67.222.222").unwrap(), + IpAddr::from_str("208.67.220.220").unwrap(), + IpAddr::from_str("2620:119:35::35").unwrap(), + IpAddr::from_str("2620:119:53::53").unwrap(), + ]; + + // trust_negative_responses=true means NXDOMAIN/empty NOERROR from an + // authoritative upstream won’t be retried on other servers. + let ns = + hickory_resolver::config::NameServerConfigGroup::from_ips_clear( + &ips, 53, true, + ); + + hickory_resolver::Resolver::builder_with_config( + hickory_resolver::config::ResolverConfig::from_parts( + None, + vec![], + ns, + ), + hickory_resolver::name_server::TokioConnectionProvider::default( + ), + ) + .build() + }) +} + +pub async fn resolve_host_public_ip() -> anyhow::Result { + opendns_resolver() + .lookup_ip("myip.opendns.com.") + .await + .context("Failed to query OpenDNS resolvers for host public IP")? + .into_iter() + .map(|ip| ip.to_string()) + .next() + .context("OpenDNS call for public IP didn't return anything") +} + // ===== // SSL // ===== diff --git a/bin/periphery/src/state.rs b/bin/periphery/src/state.rs index cfe434dcf..0c11a59fb 100644 --- a/bin/periphery/src/state.rs +++ b/bin/periphery/src/state.rs @@ -10,7 +10,7 @@ use cache::CloneCache; use komodo_client::entities::docker::container::ContainerStats; use noise::key::{RotatableKeyPair, SpkiPublicKey}; use periphery_client::transport::EncodedTransportMessage; -use tokio::sync::{Mutex, RwLock, mpsc, oneshot}; +use tokio::sync::{Mutex, OnceCell, RwLock, mpsc, oneshot}; use tokio_util::sync::CancellationToken; use transport::channel::BufferedChannel; use uuid::Uuid; @@ -18,6 +18,7 @@ use uuid::Uuid; use crate::{ config::periphery_config, docker::DockerClient, + helpers::resolve_host_public_ip, stats::StatsClient, terminal::{StdinMsg, Terminal}, }; @@ -297,3 +298,18 @@ pub fn container_stats() -> &'static ArcSwap { OnceLock::new(); CONTAINER_STATS.get_or_init(Default::default) } + +pub async fn host_public_ip() -> Option<&'static String> { + static PUBLIC_IPS: OnceCell> = OnceCell::const_new(); + PUBLIC_IPS + .get_or_init(|| async { + resolve_host_public_ip() + .await + .inspect_err(|e| { + warn!("Failed to resolve host public ip | {e:#}") + }) + .ok() + }) + .await + .as_ref() +} diff --git a/client/core/rs/src/entities/server.rs b/client/core/rs/src/entities/server.rs index f8059e789..3a8e60dfe 100644 --- a/client/core/rs/src/entities/server.rs +++ b/client/core/rs/src/entities/server.rs @@ -36,6 +36,8 @@ pub struct ServerListItemInfo { /// External address of the server (reachable by users). /// Used with links. pub external_address: Option, + /// Host public ip, if it could be resolved. + pub public_ip: Option, /// Whether server is configured to send disconnected alerts. pub send_unreachable_alerts: bool, /// Whether server is configured to send cpu alerts. @@ -358,6 +360,8 @@ pub struct PeripheryInformation { pub stats_polling_rate: Timelength, /// Whether Periphery is successfully connected to docker daemon. pub docker_connected: bool, + /// The host public ip, if it can be resolved. + pub public_ip: Option, } /// Info about an active terminal on a server. diff --git a/client/core/ts/src/types.ts b/client/core/ts/src/types.ts index a4e95207a..d796425de 100644 --- a/client/core/ts/src/types.ts +++ b/client/core/ts/src/types.ts @@ -1771,6 +1771,10 @@ export interface PeripheryInformation { container_terminals_disabled: boolean; /** The rate the system stats are being polled from the system */ stats_polling_rate: Timelength; + /** Whether Periphery is successfully connected to docker daemon. */ + docker_connected: boolean; + /** The host public ip, if it can be resolved. */ + public_ip?: string; } export type GetPeripheryInformationResponse = PeripheryInformation; @@ -3927,6 +3931,8 @@ export interface ServerListItemInfo { * Used with links. */ external_address?: string; + /** Host public ip, if it could be resolved. */ + public_ip?: string; /** Whether server is configured to send disconnected alerts. */ send_unreachable_alerts: boolean; /** Whether server is configured to send cpu alerts. */ diff --git a/frontend/public/client/types.d.ts b/frontend/public/client/types.d.ts index 9c1a3eab1..572859859 100644 --- a/frontend/public/client/types.d.ts +++ b/frontend/public/client/types.d.ts @@ -1929,6 +1929,10 @@ export interface PeripheryInformation { container_terminals_disabled: boolean; /** The rate the system stats are being polled from the system */ stats_polling_rate: Timelength; + /** Whether Periphery is successfully connected to docker daemon. */ + docker_connected: boolean; + /** The host public ip, if it can be resolved. */ + public_ip?: string; } export type GetPeripheryInformationResponse = PeripheryInformation; export type GetPermissionResponse = PermissionLevelAndSpecifics; @@ -3912,6 +3916,8 @@ export interface ServerListItemInfo { * Used with links. */ external_address?: string; + /** Host public ip, if it could be resolved. */ + public_ip?: string; /** Whether server is configured to send disconnected alerts. */ send_unreachable_alerts: boolean; /** Whether server is configured to send cpu alerts. */ diff --git a/frontend/src/components/resources/server/index.tsx b/frontend/src/components/resources/server/index.tsx index 32a1552d0..45347d3a0 100644 --- a/frontend/src/components/resources/server/index.tsx +++ b/frontend/src/components/resources/server/index.tsx @@ -19,8 +19,8 @@ import { Square, AlertCircle, CheckCircle2, - KeyRound, Loader2, + Globe, } from "lucide-react"; import { Section } from "@components/layouts"; import { Prune } from "./actions"; @@ -32,12 +32,7 @@ import { ServerConfig } from "./config"; import { DeploymentTable } from "../deployment/table"; import { ServerTable } from "./table"; import { DeleteResource, NewResource, ResourcePageHeader } from "../common"; -import { - ActionWithDialog, - ConfirmButton, - CopyButton, - StatusBadge, -} from "@components/util"; +import { ActionWithDialog, ConfirmButton, StatusBadge } from "@components/util"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@ui/tabs"; import { Card, CardHeader, CardTitle } from "@ui/card"; import { RepoTable } from "../repo/table"; @@ -51,7 +46,6 @@ import { GroupActions } from "@components/group-actions"; import { ServerTerminals } from "@components/terminal/server"; import { usePermissions } from "@lib/hooks"; import { Tooltip, TooltipContent, TooltipTrigger } from "@ui/tooltip"; -import { HoverCard, HoverCardContent, HoverCardTrigger } from "@ui/hover-card"; import { Dialog, DialogContent, @@ -489,26 +483,26 @@ export const ServerComponents: RequiredResourceComponents = { }, Info: { - Pubkey: ({ id }) => { - const public_key = useServer(id)?.info.public_key; + Version: ServerVersion, + PublicIP: ({ id }) => { + const { toast } = useToast(); + const public_ip = useServer(id)?.info.public_ip; + return ( - - - } - content={public_key} - /> - - -
- Copy Periphery Pubkey -
-
-
+
{ + public_ip && + navigator.clipboard + .writeText(public_ip) + .then(() => toast({ title: "Copied public IP" })); + }} + > + + {public_ip ?? "Unknown IP"} +
); }, - Version: ServerVersion, Cpu: ({ id }) => { const isServerAvailable = useIsServerAvailable(id); const core_count =