16

Is there anyway that I can ssh into a guest vm through virsh instead of find the ip address of the guest vm?

e.g.

what I want is ssh into a guest like this way :

$virsh ssh_or_somwthing <domain>

but not like this:

$ #1) find the guest vm's IP address:
$arp
...
$ #2) ssh someone@<IP>

4 Answers 4

9

Jacek has the right answer, but just to lay out some of the specifics:

  1. Log into the VM using the KVM GUI
  2. On the VM command line, type in:

    systemctl enable [email protected]
    systemctl start [email protected]
    

You will be asked multiple times to enter your password/accept.

  1. Reboot the VM
  2. Then, from the terminal on your main machine, type in:

    sudo virsh console your_vm_name_here
    

Obviously replacing "your_vm_name_here" with whatever the VM name is.

Then you can "ssh" directly into the VM using virsh.

3
  • 7
    This allows you to access the VM via a terminal, but this has nothing to do with SSH.
    – Jounathaen
    Dec 28, 2019 at 17:37
  • error: internal error: character device console0 is not using a PTY
    – Dave Ankin
    Jun 20, 2022 at 8:12
  • Can anyone know how to access the console without a password but a private key? I mainly ssh into the VM with PK, but via virsh console I had to provide the password, which I am totally unaware of.
    – s3cret
    Aug 9, 2023 at 1:52
1

I'm not sure about it, but I think you're looking to configure console access to the guest? It may not be the only solution (not following virsh very actively and all this stuff) - but you can setup serial console on your guest, configure your supervisor and then use virsh console domain.

Anyway - have a look at this: https://help.ubuntu.com/community/KVM/Access - I guess it may help or at least put you in some direction.

2
  • thanks :) it seems that console access is using telnet(I'am not sure about it) ?
    – gansteed
    Jan 23, 2015 at 12:20
  • 1
    Not really - telnet is different story. It's actually serial connection (kind of virtualized here)
    – Jacek
    Jan 23, 2015 at 14:23
0

You may want to take a read of SSHsetup for libvirtd

https://wiki.libvirt.org/page/SSHSetup

Seems to do what you want.

1
  • 2
    The link you provided shows how to set up ssh communications to libvirt running on another system. This uses ssh just as a tunnel between virsh (or virt-manager) and libvirt on different machines. The OP is looking to send console commands directly through virsh to the VM, using virsh as a proxy or tunnel into the VM, rather than via ssh to the VM itself. This would be useful for running a VM with no networking, but still have effectively a serial console into the VM. Sep 9, 2021 at 18:50
0

virsh itself does not supply ssh capabilities in managing the VMs*.

If we want to access the machine through ssh, we may only do that through the ssh command.

Following are the 2 steps for that.

1. Setting Up the SSH Access

For the first step there are 2 tracks

Pre-Configure the Machine (eg: Cloud-Init)

We could use cloud-init (may be also preseed.cfg/kickstart ... etc.) to install the public key.

# Cloud-init snippet
users:
  - name: your_username
    ssh-authorized-keys:
      - your_public_ssh_key

Manual Configuration

  1. Ensure that ssh daemon is running in the VM, if you have an interactive access, you could run virsh console $vm_name then set up the ssh daemon. If there's no interactive access you'll need to use any of the following:

    • virt-customize while the machine is shut off virt-customize -d "$vm_name" --run-command "command to install ssh"
      or
    • expect to send keystrokes to setup the VM, which could be found in the appendix of this answer.
      or
    • any other tool that sends keystrokes to the VM
  2. Install your public key into the VM:

    # virt-copy-in requires the virtual machine to be stopped
    #   for example this should return `shut off`
    virsh dominfo my_vm | grep State | awk -F':' '{print $2}' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//'
    # virt-copy-in takes a file argument and a directory argument
    # thus we need to use a correct filename before copying
    if [ ! -f ~/.ssh/id_rsa ]; then
        ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
    fi
    cp ~/.ssh/id_rsa.pub /tmp/authorized_keys
    # Finally, virt-copy-in may require sudo
    virt-copy-in -d "$vm_name" /tmp/authorized_keys /home/ubuntu/.ssh/
    

2. Accessing the VM

  1. Capture the IP address:
    export vm_ip_address=$(virsh domifaddr my_vm | awk '/ipv4/ {print $4}' | awk -F'/' '{print $1}')
    
  2. ssh into the machine
    export vm_user=ubuntu # set the correct username here
    ssh $vm_user@$vm_ip_address
    

* virsh could use ssh to communicate with remote servers, but that has nothing to do with accessing the virtual machines themselves.

Appendix

Following is an expect snippet that could be used to automate setting up the interactive console access in a non-interactive manner.

#!/usr/bin/expect -f

# Function to wait for a specific string before sending the command
proc wait_for_prompt { } {
    expect "# "   ; # Modify the expected prompt if needed
}

# Function to send a command and wait for the output
proc send_command { command } {
    send "$command\r"
    expect "# "   ; # Modify the expected prompt if needed
}

# Replace 'vm_name' with the actual name of your virtual machine
set vm_name "my_vm"

# Replace 'your_command' with the command you want to run inside the VM
set command_to_run1 "sudo apt-get install openssh-server."
set command_to_run2 "sudo systemctl start ssh"
set command_to_run3 "sudo systemctl enable ssh"

#spawn virsh start $vm_name 
# Spawn the virsh command
spawn virsh

# Wait for the virsh prompt
expect "virsh # "

# Start the virtual machine
send "start $vm_name\r"


send "console $vm_name\r"

# Wait for the console to start
# Send double enters
send_command ""
send_command ""
expect -timeout 100 "ubuntu login"


# Set password
send_command "ubuntu"
send_command "ubuntu"
# we may need to login again if prompted
send_command "ubuntu"
send_command "ubuntu"

# run the commands
send_command "$command_to_run1"
send_command "$command_to_run2"
send_command "$command_to_run3"

# Wait for the output of the command to appear
expect "your_expected_output" ; # Modify this line to match the expected output

# Exit the console
send "\x1d"
expect eof

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .