Guide to Interpreting the YAML Configuration and Connecting to IPKVM

System deployment YAML configuration tutorial

In this tutorial, we will walk you through the process of interpreting the YAML configuration provided to ServerAstra dedicated servers and colocation customers and explain how to connect to the IPKVM for remote management of your server.

Table of Contents

  1. Understanding the YAML Configuration
  2. Connecting to IPKVM via VPN
  3. Frequently Asked Questions (FAQs)

Understanding the YAML Configuration

The YAML (short for "YAML Ain't Markup Language") configuration file is a human-readable data format that provides you with essential information to set up and access your dedicated server remotely. The configuration file includes details such as system name, remote access methods, IP addresses, and operating system access.

Here is a breakdown of the sections in the YAML configuration file:

System Information

  • Name: The unique identifier for your dedicated server.

Remote Access

  • Type: The primary method for remote access, such as IPMI+IPKVM.
  • Additional Parameters: Contains VPN configurations for secure remote access to the IPKVM panel.

IP Addresses

  • IPv4: Provides the IPv4 address or subnet and gateway for your server.
  • IPv6: Provides the IPv6 address or subnet and gateway for your server.
  • Nameservers: Lists the primary and secondary nameservers for your server.

OS Access

  • Type: Specifies the method for accessing the operating system, such as SSH.
  • Endpoint: The IP address or hostname for connecting to the server.
  • Username: The default username for accessing the server.
  • Password: The default password for accessing the server.

Connecting to IPKVM via VPN

To securely connect to your server's IPKVM panel, you must first establish a VPN connection using one of the VPN configurations provided in the YAML file.

IPSEC+IKEv2 VPN Configuration

  1. Install a VPN client on your computer that supports IPSEC+IKEv2, such as StrongSwan or the built-in VPN client in your operating system.

    Windows Powershell example:

     > Add-VpnConnection -Name ServerAstra -ServerAddress log.serverastra.com -TunnelType Ikev2 -EncryptionLevel Required -AuthenticationMethod MSChapv2 -SplitTunneling
  2. Configure the VPN client using the following details from the YAML file:

    • Server: log.serverastra.com
    • Authentication method: EAP-MSCHAPv2 (Username+Password)
    • Username: (username)
    • Password: (password)
  3. Connect to the VPN using the configured settings.

Wireguard VPN Configuration

  1. Install the Wireguard client on your computer.

  2. Create a new Wireguard configuration file with the following details from the YAML file:

    • Peer:
      • PublicKey: WKqalZsTLD3cfs/d4WHwuL2k480DIpDtRW2q22vmXAY=
      • AllowedIPs: (AllowedIPs from configuration)
      • Endpoint: log.serverastra.com:51820
    • Interface:
      • PrivateKey: (PrivateKey from file)
      • Address: (Address from file)

    End result should look like this:

     [Interface]
     PrivateKey = xxx
     Address = xxx
    
     [Peer]
     PublicKey = WKqalZsTLD3cfs/d4WHwuL2k480DIpDtRW2q22vmXAY=
     AllowedIPs = 10.127.0.0/24, 10.40.91.0/24
     Endpoint = log.serverastra.com:51820
  3. Import the configuration file into the Wireguard client and connect to the VPN.

Accessing the IPKVM Panel

Once you have successfully connected to the VPN, follow these steps to access the IPKVM panel:

  1. Open a web browser and navigate to the panel URL provided in the YAML file (for example https://10.40.91.10).

  2. Enter the username and password from the YAML file:

    • Username: (username)
    • Password: (password)
  3. Once logged in, you should be able to access your server's IPKVM panel and remotely manage your dedicated server, including power cycling, monitoring hardware status, and accessing the server console.

Frequently Asked Questions (FAQs)

Q: Can I use a different VPN client for connecting to the IPKVM panel?

As long as the VPN client supports the protocols listed in the YAML file (IPSEC+IKEv2 or Wireguard), you can use any VPN client that meets these requirements.

Q: I'm unable to connect to the VPN. What should I do?

Ensure that you have entered the correct configuration details from the YAML file into your VPN client. If you still encounter issues, contact ServerAstra support for assistance.

Q: What if I lose my YAML configuration file?

If you lose your YAML configuration file or need to retrieve your server access credentials, please contact our support.

Q: Can file processing be automated?

Yes, here's examples of code in different languages:

Python

Prerequisites

# pip install pyyaml requests
import yaml
import requests

# Load YAML configuration from file
with open('server.yaml', 'r') as file:
    yaml_object = yaml.safe_load(file)

# Access login, password, IPMI link, and system name
system_name = yaml_object['System']['Name']
remote_access_type = yaml_object['System']['Remote Access']['Type']
ipmi_url = yaml_object['System']['Remote Access']['Additional Parameters']['Panel']['URL']
login = yaml_object['System']['Remote Access']['Additional Parameters']['Panel']['Username']
password = yaml_object['System']['Remote Access']['Additional Parameters']['Panel']['Password']

# Send login, password, and IPMI link to an external JSON API
json_data = {
    'login': login,
    'password': password,
    'ipmi_url': ipmi_url,
}

response = requests.post('https://example-json-api.com/path', json=json_data)
print(response.status_code)

# Send system name to an external REST API
rest_data = {
    'system_name': system_name,
}

response = requests.post('https://example-rest-api.com/path', data=rest_data)
print(response.status_code)

PHP

Prerequisites

# composer require symfony/yaml
<?php
require_once 'vendor/autoload.php';

use Symfony\Component\Yaml\Yaml;

// Load YAML configuration from file
$yaml_string = file_get_contents('server.yaml');
$yaml_object = Yaml::parse($yaml_string);

// Access login, password, IPMI link, and system name
$system_name = $yaml_object['System']['Name'];
$remote_access_type = $yaml_object['System']['Remote Access']['Type'];
$ipmi_url = $yaml_object['System']['Remote Access']['Additional Parameters']['Panel']['URL'];
$login = $yaml_object['System']['Remote Access']['Additional Parameters']['Panel']['Username'];
$password = $yaml_object['System']['Remote Access']['Additional Parameters']['Panel']['Password'];

// Send login, password, and IPMI link to an external JSON API
$json_data = [
    'login' => $login,
    'password' => $password,
    'ipmi_url' => $ipmi_url,
];

$ch = curl_init('https://example-json-api.com/path');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($json_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen(json_encode($json_data)),
]);
$response = curl_exec($ch);
$http_status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $http_status_code;

// Send system name to an external REST API
$rest_data = [
    'system_name' => $system_name,
];

$ch = curl_init('https://example-rest-api.com/path');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($rest_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/x-www-form-urlencoded',
    'Content-Length: ' . strlen(http_build_query($rest_data)),
]);
$response = curl_exec($ch);
$http_status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $http_status_code;

C

Prerequisites

> Install-Package YamlDotNet
> Install-Package System.Net.Http.Json
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using YamlDotNet.Serialization;

namespace YamlParsingExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // Load YAML configuration from file
            var yamlString = await File.ReadAllTextAsync("server.yaml");
            var deserializer = new DeserializerBuilder().Build();
            var yamlObject = deserializer.Deserialize<dynamic>(yamlString);

            // Access login, password, IPMI link, and system name
            string systemName = yamlObject["System"]["Name"];
            string remoteAccessType = yamlObject["System"]["Remote Access"]["Type"];
            string ipmiUrl = yamlObject["System"]["Remote Access"]["Additional Parameters"]["Panel"]["URL"];
            string login = yamlObject["System"]["Remote Access"]["Additional Parameters"]["Panel"]["Username"];
            string password = yamlObject["System"]["Remote Access"]["Additional Parameters"]["Panel"]["Password"];

            // Send login, password, and IPMI link to an external JSON API
            var jsonData = new
            {
                login = login,
                password = password,
                ipmi_url = ipmiUrl
            };

            using (var httpClient = new HttpClient())
            {
                var response = await httpClient.PostAsJsonAsync("https://example-json-api.com/path", jsonData);
                Console.WriteLine(response.StatusCode);
            }

            // Send system name to an external REST API
            var restData = new
            {
                system_name = systemName
            };

            using (var httpClient = new HttpClient())
            {
                var response = await httpClient.PostAsJsonAsync("https://example-rest-api.com/path", restData);
                Console.WriteLine(response.StatusCode);
            }
        }
    }
}

Rust

Prerequisites

Add the following dependencies to your Cargo.toml:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1.0", features = ["full"] }
use serde::{Deserialize, Serialize};
use serde_yaml;
use reqwest;
use std::fs;
use std::collections::HashMap;

#[derive(Debug, Deserialize)]
struct System {
    System: HashMap<String, serde_yaml::Value>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Load YAML configuration from file
    let yaml_string = fs::read_to_string("server.yaml").unwrap();
    let yaml_object: System = serde_yaml::from_str(&yaml_string).unwrap();

    // Access login, password, IPMI link, and system name
    let system_name = &yaml_object.System["Name"];
    let remote_access_type = &yaml_object.System["Remote Access"]["Type"];
    let ipmi_url = &yaml_object.System["Remote Access"]["Additional Parameters"]["Panel"]["URL"];
    let login = &yaml_object.System["Remote Access"]["Additional Parameters"]["Panel"]["Username"];
    let password = &yaml_object.System["Remote Access"]["Additional Parameters"]["Panel"]["Password"];

    // Send login, password, and IPMI link to an external JSON API
    let json_data = [
        ("login", login),
        ("password", password),
        ("ipmi_url", ipmi_url),
    ];

    let client = reqwest::Client::new();
    let response = client.post("https://example-json-api.com/path")
        .json(&json_data)
        .send()
        .await?;

    println!("Status: {}", response.status());

    // Send system name to an external REST API
    let rest_data = [
        ("system_name", system_name),
    ];

    let response = client.post("https://example-rest-api.com/path")
        .form(&rest_data)
        .send()
        .await?;

    println!("Status: {}", response.status());

    Ok(())
}

Golang

Prerequisites

# go get gopkg.in/yaml.v2
# go get -u github.com/go-resty/resty/v2
package main

import (
    "fmt"
    "gopkg.in/yaml.v2"
    "io/ioutil"
    "github.com/go-resty/resty/v2"
)

type System struct {
    System map[string]interface{} `yaml:"System"`
}

func main() {
    // Load YAML configuration from file
    yamlFile, err := ioutil.ReadFile("server.yaml")
    if err != nil {
        panic(err)
    }

    var yamlObject System
    err = yaml.Unmarshal(yamlFile, &yamlObject)
    if err != nil {
        panic(err)
    }

    // Access login, password, IPMI link, and system name
    systemName := yamlObject.System["Name"].(string)
    remoteAccessType := yamlObject.System["Remote Access"].(map[interface{}]interface{})["Type"].(string)
    ipmiURL := yamlObject.System["Remote Access"].(map[interface{}]interface{})["Additional Parameters"].(map[interface{}]interface{})["Panel"].(map[interface{}]interface{})["URL"].(string)
    login := yamlObject.System["Remote Access"].(map[interface{}]interface{})["Additional Parameters"].(map[interface{}]interface{})["Panel"].(map[interface{}]interface{})["Username"].(string)
    password := yamlObject.System["Remote Access"].(map[interface{}]interface{})["Additional Parameters"].(map[interface{}]interface{})["Panel"].(map[interface{}]interface{})["Password"].(string)

    // Send login, password, and IPMI link to an external JSON API
    client := resty.New()

    jsonData := map[string]string{
        "login":    login,
        "password": password,
        "ipmi_url": ipmiURL,
    }

    resp, err := client.R().SetBody(jsonData).Post("https://example-json-api.com/path")
    if err != nil {
        panic(err)
    }
    fmt.Printf("Status: %v\n", resp.Status())

    // Send system name to an external REST API
    restData := map[string]string{
        "system_name": systemName,
    }

    resp, err = client.R().SetFormData(restData).Post("https://example-rest-api.com/path")
    if err != nil {
        panic(err)
    }
    fmt.Printf("Status: %v\n", resp.Status())
}

Should you have any questions or require further assistance, don't hesitate to contact our support team.