Tuesday, January 13, 2026

Debian: Console Russification

Russification takes place in three key stages: configuring locales, if necessary — checking and installing console fonts and encoding, and then configuring the Russian keyboard layout.

Installing and Configuring the Russian Locale.

The locale defines the system message language, date, time, and number formats. The main step is to generate the Russian locale:
1. Install or update the locales package:
sudo apt update
sudo apt install locales


2. Configure the locale using the dpkg-reconfigure utility:
sudo dpkg-reconfigure locales

In the opened text menu, use the spacebar to select the item ru_RU.UTF-8 and press "Enter". On the next screen, choose ru_RU.UTF-8 as the default system locale and press "Enter" again.

Configuring Console Encoding and Font.

The next step is to configure the local console to use UTF-8 and the correct font.
1. Install the console setup package:
sudo apt install console-setup

2. Configure the console font and encoding:
sudo dpkg-reconfigure console-setup

In the menu that appears, select sequentially:
Encoding: UTF-8;
Font: For Cyrillic support, Terminus or Fixed are good choices, select one of them;
Font size: You can leave it as 8x16 (a readable option);
Character set for the console: Be sure to choose an option that includes Cyrillic (for example, Combined - Latin; Slavic and non-Slavic Cyrillic).

The settings should apply automatically. If not, reboot the machine or switch between virtual consoles and back.

Configuring the Russian Keyboard Layout.

After configuring the locale, messages may become Russian, but to input Cyrillic text in the console, you will also need to configure the keyboard.
1. Install the configuration package:
sudo apt install keyboard-configuration

2. Configure the layout:
sudo dpkg-reconfigure keyboard-configuration

In the menu that appears, sequentially select the appropriate keyboard model (can be left as default), layout (Russian), layout variant, and the key for switching languages (for example, Alt+Shift).

Additionally: To find out the current keyboard model, execute:
grep XKBMODEL /etc/default/keyboard

Additional Steps and Diagnostics:

After all configurations, reboot the system or at least log out of the console and log back in.
To check the results, run the command "locale". If everything is configured correctly, the LANG line and most others will show ru_RU.UTF-8.

Tuesday, December 23, 2025

Debian: Configuring VMware VM Customization Specifications for Debian GNU/Linux OS

Unfortunately, when using "VM Customization Specifications" to deploy Debian OS, the "open-vm-tools" scripts cannot correctly configure certain parameters for this system. To solve this issue, we'll use a custom script that will handle the functionality that doesn't work properly in the tools themselves.

Execute the following steps to configure "VM Customization Specifications":

1. Prepare a Debian OS template with the necessary software that should already be included with new hosts.
2. Make sure to install "open-vm-tools" and verify that the "vmtoolsd" service is set to autostart:
sudo apt-get install open-vm-tools
sudo systemctl enable vmtoolsd && sudo systemctl start vmtoolsd


3. Enable support for customization scripts:
sudo vmware-toolbox-cmd config set deployPkg enable-custom-scripts true

To check the current status of the parameter, execute:
sudo vmware-toolbox-cmd config get deployPkg enable-custom-scripts

4. Next, configure "VM Customization Specifications" on vCenter Server. During configuration, specify: OS type - Linux, hostname generation rules, time zone, TCP/IP settings, and add the following script:

#!/bin/bash

# Function to convert subnet mask to CIDR prefix
mask2cidr() {
    local mask=$1
    local n=0
    IFS=.

    for byte in $mask; do
        case $byte in
            255) n=$((n+8));;
            254) n=$((n+7));;
            252) n=$((n+6));;
            248) n=$((n+5));;
            240) n=$((n+4));;
            224) n=$((n+3));;
            192) n=$((n+2));;
            128) n=$((n+1));;
            0);;
            *) echo 24; return 1;;
        esac
    done

    echo $n
}

# Function to determine network management method with priority: NM -> SystemD -> Ifupdown
get_network_manager() {
    local interface=$1

    # 1. Check NetworkManager first
    if command -v nmcli >/dev/null 2>&1; then
        # Check if the interface is managed by NetworkManager
        if nmcli -t -f DEVICE device 2>/dev/null | grep -q "^${interface}$"; then
            echo "NetworkManager"
            return
        fi

        # Check if NetworkManager is active as a service
        if systemctl is-active NetworkManager >/dev/null 2>&1; then
            echo "NetworkManager"
            return
        fi

        # Check if there is a NetworkManager connection for this interface
        if nmcli -t -f NAME,DEVICE connection show 2>/dev/null | grep -q ":${interface}$"; then
            echo "NetworkManager"
            return
        fi
    fi

    # 2. Check systemd-networkd
    if systemctl is-active systemd-networkd >/dev/null 2>&1 && \
       systemctl is-active systemd-resolved >/dev/null 2>&1; then
        echo "SystemD"
        return
    fi

    # 3. Check ifupdown (traditional Debian method)
    if [ -f "/etc/network/interfaces" ]; then
        # Check if the interface is mentioned in the configuration
        if grep -q -E "^(auto|allow-hotplug|iface|mapping).*${interface}" /etc/network/interfaces; then
            echo "Ifupdown"
            return
        fi

        # Check for configs in interfaces.d
        if [ -d "/etc/network/interfaces.d" ]; then
            for config in /etc/network/interfaces.d/*; do
                if [ -f "$config" ] && grep -q "${interface}" "$config"; then
                    echo "Ifupdown"
                    return
                fi
            done
        fi
    fi

    # Check if the networking service (ifupdown) is active
    if systemctl is-active networking >/dev/null 2>&1; then
        echo "Ifupdown"
        return
    fi

    # 4. If nothing is found, check by service presence
    if systemctl is-enabled NetworkManager >/dev/null 2>&1; then
        echo "NetworkManager"
    elif systemctl is-enabled systemd-networkd >/dev/null 2>&1; then
        echo "SystemD"
    elif systemctl is-enabled networking >/dev/null 2>&1; then
        echo "Ifupdown"
    else
        # If nothing is determined, use ifupdown as a fallback
        echo "Ifupdown"
    fi
}

# Function to configure NetworkManager
configure_networkmanager() {
    local interface=$1
    local bootproto=$2
    local ipaddr=$3
    local netmask=$4
    local gateway=$5
    local dns_servers=$6
    local domain=$7

    # Delete existing connection for this interface
    nmcli connection delete "$interface" 2>/dev/null || true
    nmcli connection delete "Wired connection 1" 2>/dev/null || true
    nmcli connection delete "System ${interface}" 2>/dev/null || true

    # Create a new connection
    if [ "$bootproto" = "static" ]; then
        local prefix_length=$(mask2cidr "$netmask")
        nmcli con add type ethernet con-name "$interface" ifname "$interface" ipv4.method manual \
            ipv4.addresses "${ipaddr}/${prefix_length}" \
            ipv4.gateway "$gateway" \
            ipv4.dns "$dns_servers" \
            ipv4.dns-search "$domain" \
            autoconnect yes
    else
        nmcli con add type ethernet con-name "$interface" ifname "$interface" \
            ipv4.method auto autoconnect yes
    fi

    # Activate the connection
    nmcli con up "$interface"
}

# Function to configure SystemD networkd
configure_systemd() {
    local interface=$1
    local bootproto=$2
    local ipaddr=$3
    local netmask=$4
    local gateway=$5
    local dns_servers=$6
    local domain=$7
    local dns_from_dhcp=$8

    # Make sure the service is active
    systemctl enable systemd-networkd 2>/dev/null || true
    systemctl start systemd-networkd 2>/dev/null || true

    # Clear the /etc/systemd/network directory
    rm -rf /etc/systemd/network/*

    # Create basic configuration for loopback interface
    mkdir -p /etc/systemd/network
    cat > /etc/systemd/network/00-loopback.network <<EOF
[Match]
Name=lo

[Network]
Address=127.0.0.1/8
Address=::1/128
EOF

    # Create configuration for the main interface
    CONFIG_FILE="/etc/systemd/network/10-${interface}.network"

    if [ "$bootproto" = "static" ]; then
        if [ -z "$ipaddr" ] || [ -z "$netmask" ]; then
            echo "Error: IPADDR and NETMASK are required for static configuration"
            exit 1
        fi

        prefix_length=$(mask2cidr "$netmask")
        if [ -z "$prefix_length" ]; then
            prefix_length=24
        fi

        # Create config for static IP
        cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$interface

[Network]
Address=$ipaddr/$prefix_length
EOF

        if [ -n "$gateway" ]; then
            echo "Gateway=$gateway" >> "$CONFIG_FILE"
        fi

        # Add DNS servers
        if [ -n "$dns_servers" ]; then
            for dns in $dns_servers; do
                echo "DNS=$dns" >> "$CONFIG_FILE"
            done
        fi
    else
        # Create config for DHCP
        cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$interface

[Network]
DHCP=ipv4

[DHCPv4]
UseDomains=true
EOF

        # Configure DNS usage
        if [ "$dns_from_dhcp" = "yes" ]; then
            echo "UseDNS=yes" >> "$CONFIG_FILE"
        else
            echo "UseDNS=no" >> "$CONFIG_FILE"
            if [ -n "$dns_servers" ]; then
                for dns in $dns_servers; do
                    echo "DNS=$dns" >> "$CONFIG_FILE"
                done
            fi
        fi
    fi

    # Configure systemd-resolved if needed
    if [ -n "$dns_servers" ] || [ -n "$domain" ]; then
        mkdir -p /etc/systemd/resolved.conf.d
        cat > /etc/systemd/resolved.conf.d/10-${interface}.conf <<EOF
[Resolve]
EOF

        if [ -n "$dns_servers" ]; then
            echo "DNS=$dns_servers" >> /etc/systemd/resolved.conf.d/10-${interface}.conf
        fi

        if [ -n "$domain" ]; then
            echo "Domains=$domain" >> /etc/systemd/resolved.conf.d/10-${interface}.conf
        fi

        systemctl enable systemd-resolved 2>/dev/null || true
        systemctl start systemd-resolved 2>/dev/null || true

        # Create symlink for resolv.conf
        ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf 2>/dev/null || true
    fi

    systemctl restart systemd-networkd

    if systemctl is-active systemd-resolved >/dev/null 2>&1; then
        systemctl restart systemd-resolved
    fi
}

# Function to configure Ifupdown (/etc/network/interfaces)
configure_ifupdown() {
    local interface=$1
    local bootproto=$2
    local ipaddr=$3
    local netmask=$4
    local gateway=$5
    local dns_servers=$6
    local domain=$7

    echo "Configuring interface $interface using ifupdown" >&2

    # Create base interfaces file if it doesn't exist
    if [ ! -f /etc/network/interfaces ]; then
        mkdir -p /etc/network
        cat > /etc/network/interfaces <<EOF
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback
EOF
    fi

    # Remove ALL configuration for this interface
    # Create temporary file without current interface configuration
    tmpfile=$(mktemp)
    in_block=0

    while IFS= read -r line; do
        # Check if a new interface block starts
        if [[ "$line" =~ ^(auto|allow-hotplug|iface)[[:space:]]+$interface([[:space:]]|$) ]]; then
            in_block=1
            continue
        fi

        # If we are inside a block and encounter another block start, exit the block
        if [[ $in_block -eq 1 && "$line" =~ ^(auto|allow-hotplug|iface)[[:space:]]+ ]]; then
            in_block=0
        fi

        # If we are not inside the block of the interface being removed, save the line
        if [[ $in_block -eq 0 ]]; then
            echo "$line" >> "$tmpfile"
        fi
    done < /etc/network/interfaces

    # Copy back and remove temporary file
    mv "$tmpfile" /etc/network/interfaces
    chmod 644 /etc/network/interfaces

    # Remove possible duplicate empty lines
    sed -i '/^$/N; /^\n$/D' /etc/network/interfaces
    sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' /etc/network/interfaces

    # Add new configuration
    {
        echo ""
        echo "auto $interface"
        if [ "$bootproto" = "static" ]; then
            echo "iface $interface inet static"
            echo "    address $ipaddr"
            echo "    netmask $netmask"
            [ -n "$gateway" ] && echo "    gateway $gateway"
            [ -n "$dns_servers" ] && echo "    dns-nameservers $dns_servers"
            [ -n "$domain" ] && echo "    dns-search $domain"
        else
            echo "iface $interface inet dhcp"
        fi
    } >> /etc/network/interfaces

    # Configure DNS via resolvconf if installed
    if command -v resolvconf >/dev/null 2>&1; then
        # Create temporary file for resolvconf
        TMP_RESOLV="/tmp/resolv.conf.${interface}"
        echo "# Generated by network configuration script" > "$TMP_RESOLV"

        if [ -n "$domain" ]; then
            echo "domain $domain" >> "$TMP_RESOLV"
            echo "search $domain" >> "$TMP_RESOLV"
        fi

        if [ -n "$dns_servers" ]; then
            for dns in $dns_servers; do
                echo "nameserver $dns" >> "$TMP_RESOLV"
            done
        fi

        # Update resolvconf
        resolvconf -a "${interface}" < "$TMP_RESOLV" 2>/dev/null || true
        rm -f "$TMP_RESOLV"
    else
        # Direct configuration of /etc/resolv.conf
        if [ -n "$dns_servers" ] || [ -n "$domain" ]; then
            echo "# Generated by network configuration script" > /etc/resolv.conf

            if [ -n "$domain" ]; then
                echo "domain $domain" >> /etc/resolv.conf
                echo "search $domain" >> /etc/resolv.conf
            fi

            if [ -n "$dns_servers" ]; then
                for dns in $dns_servers; do
                    echo "nameserver $dns" >> /etc/resolv.conf
                done
            fi
        fi
    fi

    # Restart network service
    if systemctl is-active networking >/dev/null 2>&1; then
        systemctl restart networking
    else
        # Old method of network restart
        ifdown "$interface" 2>/dev/null || true
        ifup "$interface" 2>/dev/null || true
    fi
}

# --- Function to clean logs and temporary files ---
clean_system() {
    # Clean logs (preserving directory structure)
    find /var/log -type f -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null || true
    find /var/log -type f -name "*.gz" -delete 2>/dev/null || true
    find /var/log -type f -name "*.old" -delete 2>/dev/null || true
    find /var/log -type f -name "lastlog" -exec rm -f {} \; 2>/dev/null || true

    # Clean temporary files
    rm -rf /tmp/* 2>/dev/null || true
    rm -rf /var/tmp/* 2>/dev/null || true

    # Clean command history and user data
    for user_home in /home/*; do
        if [[ -d "$user_home" ]]; then
            user=$(basename "$user_home")
            # Clean bash_history and other histories
            truncate -s 0 "$user_home/.bash_history" 2>/dev/null || true
            # Clean application caches
            rm -rf "$user_home/.cache/*" 2>/dev/null || true
        fi
    done

    # Clean root
    truncate -s 0 /root/.bash_history 2>/dev/null || true
    rm -rf /root/.cache/* 2>/dev/null || true

    # Delete random seed files
    rm -f /var/lib/systemd/random-seed 2>/dev/null || true
    
    # Reset machine-id
    truncate -s 0 /etc/machine-id
    rm /var/lib/dbus/machine-id
    ln -s /etc/machine-id /var/lib/dbus/machine-id
}

# --- Function to delete SSH host keys ---
reset_ssh_keys() {
    rm -f /etc/ssh/ssh_host_* 2>/dev/null || true

    # Regenerate SSH server keys
    if command -v dpkg-reconfigure >/dev/null 2>&1; then
        dpkg-reconfigure -f noninteractive openssh-server 2>/dev/null || true
    fi

    # Alternative method for Debian
    if [ -x /usr/sbin/sshd ]; then
        /usr/sbin/sshd-keygen -A 2>/dev/null || true
    fi
}

# ============================================================
# Main script logic
# ============================================================
if [ "$1" = "precustomization" ]; then
    # Perform system cleanup
    clean_system

    # Check and create /etc/network/interfaces
    if [ ! -f /etc/network/interfaces ]; then
        echo "Creating /etc/network/interfaces file"
        mkdir -p /etc/network
        cat > /etc/network/interfaces <<EOF
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback
EOF
    fi

    # Check and create /etc/sysconfig/network-scripts directory if needed
    if [ ! -d "/etc/sysconfig/network-scripts" ]; then
        mkdir -p /etc/sysconfig/network-scripts 2>/dev/null || true
    fi

    # Pre-configuration stage
    VMCUST_DIR=$(ls -d /var/run/.vmware-imgcust* 2>/dev/null | head -n 1)
    if [ -n "$VMCUST_DIR" ]; then
        CUST_CFG_PATH="$VMCUST_DIR/cust.cfg"
        if [ -f "$CUST_CFG_PATH" ]; then
            cp "$CUST_CFG_PATH" "/root/cust.cfg"
        fi
    fi

elif [ "$1" = "postcustomization" ]; then
    # Post-configuration stage
    reset_ssh_keys

    if [ ! -f "/root/cust.cfg" ]; then
        echo "Error: configuration file /root/cust.cfg not found"
        exit 1
    fi

    CFG_FILE="/root/cust.cfg"

    # Parse configuration parameters
    BOOTPROTO=$(awk -F' = ' '/^BOOTPROTO/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
    IPADDR=$(awk -F' = ' '/^IPADDR/ {line=$2} END{print line}' "$CFG_FILE")
    NETMASK=$(awk -F' = ' '/^NETMASK/ {line=$2} END{print line}' "$CFG_FILE")
    GATEWAY=$(awk -F' = ' '/^GATEWAY/ {line=$2} END{print line}' "$CFG_FILE")
    HOSTNAME=$(awk -F' = ' '/^HOSTNAME/ {line=$2} END{print line}' "$CFG_FILE")
    DOMAIN=$(awk -F' = ' '/^DOMAINNAME/ {line=$2} END{print line}' "$CFG_FILE")
    MACADDR=$(awk -F' = ' '/^MACADDR/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
    DNS_SERVERS=$(awk -F' = ' '/^NAMESERVER\|[0-9]/ {print $2}' "$CFG_FILE" | tr '\n' ' ' | sed 's/ $//')
    DNS_FROM_DHCP=$(awk -F' = ' '/^DNSFROMDHCP/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
    TIMEZONE=$(awk -F' = ' '/^TIMEZONE/ {line=$2} END{print line}' "$CFG_FILE")
    UTC=$(awk -F' = ' '/^UTC/ {line=$2} END{print tolower(line)}' "$CFG_FILE")

    # Determine network interface
    INTERFACE=$(ip -o link | awk -v mac="$MACADDR" 'tolower($0) ~ mac {gsub(":", "", $2); print $2}')

    if [ -z "$INTERFACE" ]; then
        INTERFACE=$(ip route | awk '/default/ {print $5; exit}')
    fi

    if [ -z "$INTERFACE" ]; then
        # Last attempt: take the first Ethernet interface
        INTERFACE=$(ip -o link | awk -F': ' '$2 !~ /^lo|virbr|docker|veth/ {print $2; exit}' | sed 's/@.*//')
    fi

    if [ -z "$INTERFACE" ]; then
        echo "Error: could not determine network interface"
        exit 1
    fi

    # Determine network management method
    NET_MGR=$(get_network_manager "$INTERFACE")
    echo "Determined network management method: $NET_MGR for interface $INTERFACE"

    case "$NET_MGR" in
        "NetworkManager")
            configure_networkmanager "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
                "$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
            ;;
        "SystemD")
            configure_systemd "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
                "$GATEWAY" "$DNS_SERVERS" "$DOMAIN" "$DNS_FROM_DHCP"
            ;;
        "Ifupdown")
            configure_ifupdown "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
                "$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
            ;;
        *)
            echo "Unknown network management method, using ifupdown as fallback"
            configure_ifupdown "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
                "$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
            ;;
    esac

    # Common settings
    hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || echo "$HOSTNAME" > /etc/hostname
    sed -i "/127\.0\.1\.1/d" /etc/hosts
    echo "127.0.1.1 $HOSTNAME.$DOMAIN $HOSTNAME" >> /etc/hosts

    # Configure time zone
    if [ -n "$TIMEZONE" ]; then
        timedatectl set-timezone "$TIMEZONE" 2>/dev/null || true

        # Alternative method for Debian
        if [ -f "/usr/share/zoneinfo/$TIMEZONE" ]; then
            cp "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime 2>/dev/null || true
            echo "$TIMEZONE" > /etc/timezone 2>/dev/null || true
        fi
    fi

    # Configure BIOS time format (UTC or local)
    if [ -n "$UTC" ]; then
        if [ "$UTC" = "yes" ]; then
            # Set UTC time in BIOS
            timedatectl set-local-rtc 0 2>/dev/null || true
        else
            # Set local time in BIOS
            timedatectl set-local-rtc 1 2>/dev/null || true
        fi
    fi

    # Save configuration
    CONFIG_LOG="/root/vm-customization.log"
    {
        echo "=========================================="
        echo "Configuration completed: $(date)"
        echo "=========================================="
        echo "CONFIG_SOURCE=$CFG_FILE"
        echo "BOOTPROTO=$BOOTPROTO"
        echo "INTERFACE=$INTERFACE"
        echo "NETWORK_MANAGER=$NET_MGR"
        echo "HOSTNAME=$HOSTNAME"
        echo "DOMAIN=$DOMAIN"
        echo "TIMEZONE=$TIMEZONE"
        echo "UTC=$UTC"

        [ -n "$DNS_FROM_DHCP" ] && echo "DNS_FROM_DHCP=$DNS_FROM_DHCP"
        [ -n "$DNS_SERVERS" ] && echo "DNS_SERVERS=\"$DNS_SERVERS\""

        if [ "$BOOTPROTO" = "static" ]; then
            echo "IP_ADDRESS=$IPADDR"
            echo "NETMASK=$NETMASK"
            [ -n "$GATEWAY" ] && echo "GATEWAY=$GATEWAY"
        fi
    } > "$CONFIG_LOG"

    rm -f "/root/cust.cfg"

    # Sync changes to disk
    sync

    echo "Configuration completed successfully. Network management method: $NET_MGR"

    ##############################################################################################
    # PLACE FOR ADDITIONAL SYSTEM CONFIGURATION
    # Here you can add commands for final machine setup:
    # - Installing additional necessary software
    # - Configuration via Ansible or other configuration management systems
    # - Execution of user scripts
    # - Setting up monitoring, logging, and other services

    # Example: install basic packages
    # apt-get update && apt-get install -y curl wget net-tools

    ##############################################################################################
fi

This script covers all possible network configuration options: IfUpDown, NetworkManager, Systemd-Networkd, both with static IP and DHCP.

Friday, December 19, 2025

Debian: Setting up a swap file in Debian instead of a separate partition

Swap (swap file) is a special area on the disk that the operating system uses when physical RAM becomes insufficient. Although modern systems often have large amounts of RAM, swap can still be useful. Even with sufficient RAM, it is advisable to have a small swap (e.g., 1-2 GB) as a backup. Historically, the swap partition was placed at the end of the disk due to the peculiarities of early file systems and disk controllers: this allowed faster allocation and use of contiguous space, as placement at the disk end (closer to the "unserviced" area) reduced fragmentation and sped up access, especially on HDDs, where write speed decreases towards the center of the disk, but often there was more free space at the end without affecting the root and system partitions at the beginning. In modern realities and with virtualization use, it has become inconvenient to expand the disk and file system when necessary if a swap partition exists at the end of the disk. Therefore, this partition can be removed, and swap can be used as a file on the main partition.

To reconfigure, follow these steps:

1. Before creating a swap file, check how your swap is currently configured:
sudo swapon --show
or
free -h

2. Ensure you have enough free disk space:
df -h

It is recommended to leave at least 5% of free space on the partition after creating the swap file.

3. Create the swap file using the "dd" utility:
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress

where
bs=1M — block size of 1 MB;
count=2048 — number of blocks (resulting size: 2048 MB ≈ 2 GB);
status=progress — shows progress (not available in all versions of dd).

IMPORTANT!!!
The recommended swap size is often from 50% to 100% of the RAM amount, but no more than twice. However, for modern systems with a large amount of RAM (16 GB or more), 2-4 GB of swap is often sufficient unless you plan to use hibernation (then the swap size should be no less than the amount of RAM).

4. Restrict access to the file to only root:
sudo chmod 600 /swapfile

5. Format the file for swap:
sudo mkswap /swapfile

6. Activate swap:
sudo swapon /swapfile

7. Verify that swap is active:
sudo swapon --show
or
free -h

8. Disable the swap partition (/dev/sda3):
sudo swapoff /dev/sda3

9. Reconfigure "/etc/fstab" for correct automatic mounting of the swap file at system boot. To do this, open "fstab" for editing, find a line like:
UUID=9f3c3eb7-dbc0-45ca-9299-5bb6f9ae8958 none swap sw 0 0

Change "UUID=9f3c3eb7-dbc0-45ca-9299-5bb6f9ae8958" in the line to "/swapfile" and save the configuration file.

10. Now delete the "/dev/sda3" partition and expand the main "/dev/sda2" partition using the "fdisk" utility:
sudo fdisk /dev/sda

Enter "p" to view the partition list. Next, enter "d" and select the partition number where the swap was previously located. Check with "p" whether the correct partition was deleted. To save changes, enter "w"; to exit and cancel changes in case of an error, enter "q".

11. Expand your main partition using the freed disk space. Inside the "fdisk" utility, enter the command "e", specify your partition number, indicate how much to increase it. Exit the utility with the "w" command.

12. Finally, expand the file system of the main partition:
sudo resize2fs /dev/sda2

13. Check the changes with the commands:
lsblk -l
df -h

14. Disable hibernation mode, as this mechanism natively works only with block devices (partitions), and not with files:
echo "RESUME=none" | sudo tee /etc/initramfs-tools/conf.d/resume
sudo update-initramfs -u -k all

Wednesday, December 17, 2025

Ubuntu: Resetting the root password while accessing the server console in EFI boot mode

If you need to reset a forgotten password on Ubuntu OS installed in EFI mode, follow these steps:
  1. During boot, hold the "ESC" key to enter the GRUB menu. A "grub>" command prompt should appear.

  2. Execute the "ls" command. The console will display available partitions, for example:
    (hd0,gpt3) (hd0,gpt2) (hd0,gpt1) (lvm/ubuntu--vg-ubuntu--lv)

  3. Now, check these partitions with the commands:
    ls (hd0,gpt1)/
    ls (hd0,gpt2)/
    ls (hd0,gpt3)/
    ls (lvm/ubuntu--vg-ubuntu--lv)/


    You need to find:
    The System Partition - contains directories like familiar folders at its root: boot, home, usr, etc.
    The Boot Partition - contains:
    - The kernel file (vmlinuz): a file whose name starts with "vmlinuz-", e.g., "vmlinuz-6.8.0-31-generic".
    - The initrd file: a file whose name starts with "initrd.img-" and contains the same version as the kernel, e.g., "initrd.img-6.8.0-31-generic".
    Write down or remember the full names of these two files.

  4. Manually set the boot commands.
    Let's assume your boot partition is "(hd0,gpt2)" and the system partition is "(lvm/ubuntu--vg-ubuntu--lv)".

  5. Tell GRUB where to find the boot files (the boot partition):
    set root=(hd0,gpt2)

  6. Load the kernel:
    linux /vmlinuz-6.8.0-31-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv rw init=/bin/bash
    where
    root=/dev/mapper/ubuntu--vg-ubuntu--lv - the path to the LVM volume as the root partition;
    rw - mount for writing (ro - read-only);
    init=/bin/bash - boot directly into the root shell.

  7. Load the initrd image (necessary for LVM to work):
    initrd /initrd.img-6.8.0-31-generic

  8. Start the boot process:
    boot
    After the OS image loads, an input prompt in the format "root@(none):/#" will appear.

  9. Change the password for "root" or another user:
    passwd root

  10. Perform a reboot:
    reboot -f

If boot errors occur and the "(initramfs)" input prompt appears instead of "root@(none):/#", try mounting the filesystem manually:

  1. Create a mount point:
    mkdir /rootfs

  2. Mount your LVM volume:
    mount /dev/mapper/ubuntu--vg-ubuntu--lv /rootfs

  3. Check the mount:
    ls /rootfs
    You should see the contents of the root filesystem (/): folders like bin, home, usr, etc, etc.

  4. Use the chroot command to make the mounted partition the root for subsequent commands:
    chroot /rootfs

  5. Change the password for "root" or another user:
    passwd root
    Enter the new password twice.

  6. Reboot the system to normal mode:

    Exit chroot:
    exit

    Unmount the partition:
    umount /rootfs

    Perform a reboot:
    reboot -f

Note: Make sure to use the exact kernel version and LVM path found on your system when entering the commands.

Saturday, December 6, 2025

Debian: Different ways to configure network interfaces

To view network adapter drivers, execute:
lspci -k | grep -A2 Ethernet
The list of network interfaces can be seen with the command:
ls /sys/class/net
Let's assume our interface is named "ens33".


Interface configuration using the "ip" utility.

ip link show   #View network connections
ip -s l   #View statistics on sent/received packets
ip address show   #View TCP/IP configuration
ip link set dev ens33 up   #Enable the interface if it was disabled
ip address flush dev ens33   #Reset interface configuration
ip addr add 192.168.0.5/24 broadcast + dev ens33   #Set IP and mask
ip addr del 192.168.0.5/24 dev ens33   #Delete IP and mask (in case of error)
ip route show   #View routing table
ip route add default via 192.168.0.1 dev ens33   #Set default gateway
ip route delete default   #Delete default gateway
ip route add 192.168.10.0/24 via 192.168.0.254 dev ens33   #Add a route
ip route del 192.168.10.0/24 dev ens33 #Delete a route
echo "nameserver 192.168.0.1 8.8.8.8" | sudo tee /etc/resolv.conf   #Add DNS

These settings are temporary and will work until the OS is rebooted.


Configuring the network subsystem using the "ifupdown" method (used by default when installing without a GUI).

1. Install the package and start the service (if the "networking" service is missing):
sudo apt-get install ifupdown
sudo systemctl enable --now networking


2. To configure the interface, you need to create or edit the existing file "/etc/network/interfaces".
Specify the following parameters in the file:

For DHCP:

iface lo inet loopback
auto lo
auto ens33
iface ens33 inet dhcp



For static IP:

iface lo inet loopback
auto lo
auto ens33
iface ens33 inet static
address 192.168.1.100/24
#IP and mask
gateway 192.168.1.1 #Default gateway
up ip route add 10.0.0.0/8 via 192.168.1.200 #Static routes
metric 0

and create the file "/etc/resolv.conf" with the following content:
nameserver 192.168.0.1 #DNS1
nameserver 8.8.8.8 #DNS2


3. Restart the interface:
sudo ifdown ens33 && sudo ifup ens33
or the service:
sudo systemctl restart networking

4. Perform configuration checks:
ip address show
ip route show


If necessary to remove "ifupdown" components, execute:
sudo apt-get remove ifupdown
sudo rm -f
/etc/network/interfaces
sudo rm -rf /etc/network/interfaces.d/*
sudo rm -f /etc/resolv.conf


Configuring the network subsystem "NetworkManager" (used by default when installing with a graphical interface).

1. Install NetworkManager:
sudo apt-get install network-manager

2. Enable and start the service:
sudo systemctl enable --now NetworkManager

3. Configure NetworkManager to manage all interfaces by editing the file "/etc/NetworkManager/NetworkManager.conf": in the [ifupdown] section, change the parameter value to:
managed=true

4. Configure the network interface using the terminal utility "nmtui" or from the command line with the utility "nmcli":

Viewing:
nmcli con show   #View network connections
nmcli dev show ens33  
#View active connection on "ens33"
nmcli con show 'Wired connection 1'  
#View connection parameters

Settings for DHCP:
nmcli con mod 'Wired connection 1' ipv4.method auto
nmcli con mod 'Wired connection 1' ipv4.addresses "" ipv4.gateway ""
nmcli con mod 'Wired connection 1' ipv4.dns ""
nmcli con mod 'Wired connection 1' ipv4.routes ""
nmcli con up 'Wired connection 1'


Settings for static IP:
nmcli con mod 'Wired connection 1' ipv4.addresses 192.168.0.5/24
nmcli con mod 'Wired connection 1' ipv4.gateway 192.168.0.1
nmcli con mod 'Wired connection 1' ipv4.dns "192.168.0.1 8.8.8.8"
nmcli con mod 'Wired connection 1' +ipv4.routes "192.168.10.0/24 192.168.0.254"
nmcli con mod 'Wired connection 1' ipv4.method manual
nmcli con up 'Wired connection 1'


5. Perform configuration checks:
ip address show
ip route show



If necessary to remove "NetworkManager" components, execute:
sudo apt-get remove network-manager
sudo rm -rf /etc/NetworkManager/
sudo rm -rf /var/lib/NetworkManager/
sudo rm -f /etc/resolv.conf


Configuring the network subsystem "systemd-networkd".

1. The "systemd-networkd" service is already included in "systemd", install only "systemd-resolved", add them to autostart:
sudo apt-get install systemd-resolved
sudo systemctl enable --now systemd-networkd
sudo systemctl enable --now systemd-resolved


2. Create a configuration file (the ".network" extension is mandatory):
sudo nano /etc/systemd/network/20-wired.network

Settings for DHCP:

[Match]
Name=ens33
[Network]
DHCP=ipv4



Settings for static IP:

[Match]
Name=ens33
[Network]
Address=192.168.0.5/24
Gateway=192.168.0.1
DNS=192.168.0.1 8.8.8.8
[Route]
Destination=192.168.10.0/24
Gateway=192.168.0.254
Metric=10   #Optional


3. Restart or reload the service:
sudo systemctl restart systemd-networkd
or
sudo networkctl reload

4. Perform configuration checks:
ip address show
ip route show
resolvectl



If necessary to remove "systemd-networkd" components, execute:
sudo systemctl disable --now systemd-networkd systemd-resolved
sudo apt-get remove systemd-
resolved
sudo rm -rf /etc/systemd/network/*

sudo rm -f /etc/resolv.conf


General recommendations!!!
For simple server and virtual machine configurations, use "systemd-networkd", in this case, it is recommended to remove all other modules:
sudo apt-get remove ifupdown network-manager dhcpcd-base
sudo rm -f /etc/network/interfaces
sudo rm -rf /etc/network/interfaces.d/*
sudo rm -rf /etc/NetworkManager/
sudo rm -rf /var/lib/NetworkManager/
sudo rm -f /etc/resolv.conf

Monday, November 3, 2025

Windows: Connecting Huawei Storage System via Dataturbo Protocol

Configuration is performed as follows:

1. Perform preliminary file system configuration on the storage system:

1.1 Create a user for Dataturbo protocol authorization: go to "vStore Service->vStores". Select your vStore (default is System_vStore).


Go to the "User Management" tab and create a user (for example "dataturbo"). Specify the role "vStore DataTurbo administrator".


1.2 Create a logical port: go to "Services->Logical Ports". Select your vStore (default is System_vStore).



Create a new port "DataTurbo_Port", specify the role "Service" and protocol "DataTurbo", configure the IP address, mask, gateway for the port. Set the port type and failover mode.


1.3 Create a file system: go to "Services->File Systems". Select your vStore (default is System_vStore).



Create a file system "DataTurbo_FS", specify the security style "NTFS", volume size and sharing protocol "DataTurbo".


1.4 Configure access to the file system: click on our "DataTurbo_FS" and go to the "Shares" tab, then "DataTurbo Shares".


Select our share "/DataTurbo_FS/" and add read/write permissions to the previously created user "dataturbo".


2. Install the "OceanStor_DataTurbo_1.3.0_Windows.zip" driver on your Windows OS:

2.1 Download "OceanStor_DataTurbo_1.3.0_Windows.zip" and extract the archive to a temporary directory, launch "cmd" with elevated privileges and navigate there.

2.2 Run "install.bat".

2.3 During installation specify:
- driver installation directory;
- performance level depending on available free OS RAM (from 0 to 3);
- username for driver service operation (default - "dataturbo");
- username for driver service management and monitoring (default - "dataturbo_mgmt") and its password.


2.4 Close the console window after installation and reboot the OS.


3. Connect the share via DataTurbo protocol:

3.1 Create a directory within the Windows OS where the storage volume will be mounted (for example, "C:\dataturbo_fs").

3.2 Open the console and check the functionality of the "dataturbo" utility (for example, run "dataturbo show version").

3.3 Connect to the logical port on the storage system, use DNS name or IP configured in the previous step:
dataturbo create storage_object storage_name=OceanProtect ip_list=192.168.1.20

View connected storage systems:
dataturbo show storage_object

To delete storage system:
dataturbo delete storage_object storage_name=OceanProtect

3.4 Mount the share to the previously created directory:
dataturbo mount storage_object storage_name=OceanProtect filesystem_name=/DataTurbo_FS/ mount_dir=C:\dataturbo_fs

View current mounted shares:
dataturbo show mount_dir

To unmount the share (if necessary):
dataturbo umount mount_dir=C:\dataturbo_fs

3.5 After reboot, the share will need to be remounted. To automate this process, you can add the following script to autostart:

@echo off
timeout /t 5
dataturbo mount storage_object storage_name=OceanProtect filesystem_name=/DataTurbo_FS/ mount_dir=C:\dataturbo_fs

The script must be run as a user who is on the DataTurbo driver's whitelist. Open the "whitelist" file (by default located in "C:\Program Files\oceanstor\dataturbo\conf") in a text editor and check if your user account's SID is already on the list. If not, add it.

Tuesday, October 7, 2025

Debian: Configuring for Active Directory

Follow these steps to set up your Debian Linux OS to work with Active Directory:

1. Pre-configuration of network, DNS, full and short hostname.
Ensure the server has correct network settings and can resolve domain names:
ping dc.YOUR_FQDN
nslookup YOUR_FQDN


Replace the local domain name "localdomain" with your domain name YOUR_FQDN in the "/etc/hosts" file using the command:
sudo sed -i 's/localdomain/YOUR_FQDN/g' /etc/hosts

2. Installation of necessary packages.
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt -y install realmd \
sssd sssd-tools libnss-sss libpam-sss adcli samba-common-bin \
oddjob oddjob-mkhomedir packagekit krb5-user


3. Domain discovery and configuration of Kerberos and realmd.
Discover the domain:
sudo realm discover YOUR_FQDN

To configure Kerberos, edit the file "/etc/krb5.conf":

[libdefaults]
    default_realm = YOUR_FQDN
    dns_lookup_realm = true
    dns_lookup_kdc = true


To configure realmd, create the file "/etc/realmd.conf" with the following content:

[service]
automatic-install = yes

[active-directory]
os-name = Debian
os-version = 13


These parameters will be reflected in the computer account properties in Active Directory after joining the host to the domain.

4. Pre-configuration of SSSD.
Since the "/etc/sssd/sssd.conf" file will be overwritten when joining or leaving the domain using the "realm join" command, the best option is to create a new SSSD configuration file with custom parameters.
sudo nano /etc/sssd/conf.d/10-mysettings.conf

[domain/YOUR_FQDN]
# Add authentication provider
auth_provider = ad
# Add password change provider
chpass_provider = ad
# Short username mode, when set to "false"
use_fully_qualified_names = true
# Default shell setting
default_shell = /bin/bash
# Home directory formation rule
fallback_homedir = /home/%u@%d
# Add to ignore group policies that are inaccessible
ad_gpo_ignore_unreadable = true
# Add dynamic DNS settings
dyndns_update = true
dyndns_refresh_interval = 1800
dyndns_ttl = 1800
dyndns_update_ptr = true


Set correct permissions on the configuration file:
sudo chmod 600 /etc/sssd/conf.d/10-mysettings.conf

5. Joining the domain.
sudo realm join YOUR_FQDN
\
--membership-software=adcli \
--user=DomainAdmin


Enter the user password when prompted.

Check successful join:
id DomainAdmin@YOUR_FQDN

6. Configuring automatic home directory creation.
Edit the file "/etc/pam.d/common-session":
sudo nano /etc/pam.d/common-session

Add to the end of the file:
session optional pam_mkhomedir.so skel=/etc/skel umask=077

7. Configuring access rights.

Managing console access to the server:

Deny login to all domain users:
sudo realm deny --all
Allow login only to specific groups:
sudo realm permit -g 'Linux_Console_Users'@YOUR_FQDN
For groups with spaces in the name:
sudo realm permit -g '"Domain Linux Users"'@YOUR_FQDN
Check settings:
sudo realm list
To remove a group from access, use:
sudo realm permit -g -x 'Linux_Console_Users'@YOUR_FQDN

Managing SSH access:

Create a new file in the "/etc/ssh/sshd_config.d" directory:
sudo nano /etc/ssh/sshd_config.d/10-admins.conf

Add parameters to restrict access by groups:
AllowGroups
Linux_SSH_Users@YOUR_FQDN "Linux SSH Admins"@YOUR_FQDN

IMPORTANT!!!!
If you use the parameter value "use_fully_qualified_names = false" in the "/etc/sssd/sssd.conf" file, then when configuring SSH access, specify the short username or group name without the domain name, for example:
AllowGroups Linux_SSH_Users "Linux SSH Admins"

Also, the group names (Linux_SSH_Users and "Linux SSH Admins") and domain name (YOUR_FQDN) must be STRICTLY IN LOWERCASE!!!

Set correct permissions on the file and restart the SSH service:
sudo chmod 600 /etc/ssh/sshd_config.d/10-admins.conf
sudo systemctl restart ssh

8. Configuring sudo rights for domain groups.
Create a sudo rules file:
sudo visudo -f /etc/sudoers.d/domain_admins
Always use the "visudo" command, which prevents saving configuration with syntax errors.

Add necessary rules:

Full administrator rights (example):
%Linux_Sudoers@YOUR_FQDN ALL=(ALL:ALL) ALL
Members of the Linux_Sudoers group can now run commands with "sudo" by entering their Active Directory account password.

Limited rights (example):
%Linux_Sudoers@YOUR_FQDNALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx

For groups with spaces in the name:
%Linux\ Admins@YOUR_FQDN ALL=(ALL:ALL) ALL

Set file permissions:
sudo chmod 440 /etc/sudoers.d/domain_admins

IMPORTANT!!!!
If you use the parameter value "use_fully_qualified_names = false" in the "/etc/sssd/sssd.conf" file, then when configuring sudoers, specify the short username or group name without the domain name, for example:
%Linux_Sudoers ALL=(ALL:ALL) ALL

9. Testing the configuration.
Try logging in with a domain account:
ssh linux_admin@YOUR_FQDN@server_ip_address
Check home directory creation:
pwd
Check "sudo" functionality for users from allowed groups.
Ensure the server time is synchronized with the domain (use NTP).
Regularly check authentication logs: /var/log/auth.log.
Use SSSD logs for troubleshooting: /var/log/sssd/
Check connectivity with the domain controller:
klist
Check the ability to obtain a Kerberos ticket:
kinit


Removing a host from the domain, renaming a domain machine.

To remove your host from the domain, execute:
sudo realm leave YOUR_FQDN -v --user=DomainAdmin
This will reset all settings made in the "/etc/sssd/sssd.conf" file.

The renaming operation for Linux boils down to the following steps:
1. Remove the host from the domain.
2. Rename using the command:
sudo hostnamectl set-hostname NEW-HOSTNAME
Also change the name in the "/etc/hosts" file:
sudo sed -i 's/OLD-HOSTNAME/NEW-HOSTNAME/g' /etc/hosts
Restart the service:
sudo systemctl restart systemd-hostnamed
3. Re-join the domain with the new name:
sudo realm join YOUR_FQDN \
--membership-software=adcli \
--user=DomainAdmin

After joining the domain, you must reconfigure access using the "sudo realm permit" command, as the "/etc/sssd/sssd.conf" file, which stored the previous settings, was reset by the SSSD service when leaving the domain.