(&self, force: bool)
| 581 | } |
| 582 | |
| 583 | async fn setup(&self, force: bool) -> Result<()> { |
| 584 | if !self.shared.app_compose.gateway_enabled() { |
| 585 | info!("dstack-gateway is not enabled"); |
| 586 | return Ok(()); |
| 587 | } |
| 588 | if self.keys.gateway_app_id.is_empty() { |
| 589 | bail!("Missing allowed dstack-gateway app id"); |
| 590 | } |
| 591 | |
| 592 | info!("Setting up dstack-gateway"); |
| 593 | |
| 594 | // Get or generate key store (includes WireGuard keys and client certificate) |
| 595 | let key_store = self.get_or_generate_key_store().await?; |
| 596 | |
| 597 | if self.shared.sys_config.gateway_urls.is_empty() { |
| 598 | bail!("Missing gateway urls"); |
| 599 | } |
| 600 | // Read config and make API call |
| 601 | let response = 'out: { |
| 602 | let mut error = anyhow!("unknown error"); |
| 603 | for (i, url) in self.shared.sys_config.gateway_urls.iter().enumerate() { |
| 604 | let response = self.register_cvm(url, &key_store).await; |
| 605 | match response { |
| 606 | Ok(response) => { |
| 607 | break 'out response; |
| 608 | } |
| 609 | Err(err) => { |
| 610 | warn!("Failed to register CVM: {err:?}, retrying with next dstack-gateway"); |
| 611 | if i == 0 { |
| 612 | error = err; |
| 613 | } |
| 614 | } |
| 615 | } |
| 616 | } |
| 617 | return Err(error).context("Failed to register CVM, all dstack-gateway urls are down"); |
| 618 | }; |
| 619 | let mut wg_info = response.wg.context("Missing wg info")?; |
| 620 | |
| 621 | let client_ip = &wg_info.client_ip; |
| 622 | |
| 623 | // Sort peers by public key for consistent config generation |
| 624 | wg_info.servers.sort_by(|a, b| a.pk.cmp(&b.pk)); |
| 625 | |
| 626 | // Create WireGuard config |
| 627 | let wg_listen_port = "9182"; |
| 628 | let mut new_config = format!( |
| 629 | "[Interface]\n\ |
| 630 | PrivateKey = {}\n\ |
| 631 | ListenPort = {wg_listen_port}\n\ |
| 632 | Address = {client_ip}/32\n\n", |
| 633 | key_store.wg_sk |
| 634 | ); |
| 635 | for WireGuardPeer { pk, ip, endpoint } in &wg_info.servers { |
| 636 | let ip = ip.split('/').next().unwrap_or_default(); |
| 637 | new_config.push_str(&format!( |
| 638 | "[Peer]\n\ |
| 639 | PublicKey = {pk}\n\ |
| 640 | AllowedIPs = {ip}/32\n\ |
no test coverage detected