Add resolutions in OpenBSD VM (libvirt/qemu)

Wanted to test OpenBSD as a desktop, I spun up a VM using virt-manager (libvirt) and walked through the install process. After getting all setup, I found I could only set a few different resolutions, none of which where all that high. This is due to the fact that by default (unless you passed through a GPU into the VM) you’ll be using the vesa driver. This is fine for what I’m doing, I just want to expose more resolution options.

To fix this, you need to manually configure Xorg with the snippet below.

First, create the xorg.conf directory. Note, these commands need to be done as the root user

mkdir /etc/X11/xorg.conf.d

Then copy/paste the below into your terminal.

cat > /etc/X11/xorg.conf.d/10-virtual.conf <<EOF
Section "Device"
  Identifier   "Virtual-Card"
  Driver       "vesa"
  VendorName   "InnoTek"
  BoardName    "Virtual Graphics Adapter"
EndSection
Section "Monitor"
  Identifier   "Virtual-Monitor"
  VendorName   "InnoTek"
  ModelName    "Virtual Screen"
  HorizSync    1.0 - 1000.0
  VertRefresh  1.0 - 1000.0
EndSection
Section "Screen"
  Identifier   "Virtual-Screen"
  Device       "Virtual-Card"
  Monitor      "Virtual-Monitor"
  DefaultDepth 24
  SubSection "Display"
    Viewport   0 0
    Depth      24
    Modes "1600x900" "1368x768" "1360x768" "1280x800"
  EndSubSection
EndSection
EOF

Finally, just restart xenodm

rcctl restart xenodm

The Little known SSH ForceCommand

There may be times when you want to restrict what commands a user can issue when they attempt to login over an SSH connection. Instead of executing the users shell, you can instead execute a custom script that limits the user to a specific set of commands. This is known as ForceCommand.

There are two ways one can choose to use this. Today, I’ll describe a scenario where you don’t have permissions to modify the SSH server config (/etc/ssh/sshd_config) but still want to enforce specific commands for certain users (identified by their SSH key).

First, create a script somewhere that you have write permissions. We’ll reference this later in our config. Here’s a quick example to get you started that only allows you to get a process list (ps -ef) and print system statistics (vmstat).

#!/bin/sh
# script: /home/shane/bin/wrapper.sh 

case "$SSH_ORIGINAL_COMMAND" in
	"ps")
		ps -ef
		;;
	"vmstat")
		vmstat 1 100
		;;
	*)
		echo "Only these commands are available to you:"
		echo "ps, vmstat, cupsys stop, cupsys start"
		exit 1
		;;
esac

Be sure to set the script to be executable.

chmod +x /home/shane/bin/wrapper.sh

Now, we just need to edit our ~/.ssh/authorized_keys file to reference this script. Note, you could create multiple scripts and assign them to different users’s SSH keys to allow different commands.

command="/home/shane/bin/wrapper.sh",no-port-forwarding,no-agent-forwarding ssh-ed25519 AAAAC3NzaC....snip...

Here’s how it would look in practice.

User can only run “ps” or “vmstat”
User running “vmstat”

Create SSL Cert and Key

Sometimes during development you may find yourself needing an SSL certificate and key to test with. I’ve had to do this so much I went ahead and added the below function to my ~/.bashrc file.

createss () 
{ 
    openssl req -x509 -nodes -newkey rsa:4096 \
      -keyout ${1}.key -out ${1}.crt -days 365 \
      -subj "/C=US/ST=Ohio/L=Elida/O=ShanerOPS/OU=OPS/CN=${1}"
}

Now, I can create certs on-the-fly without having to look it up in my notes. Here’s how it looks in practice.

$ createss demo.site.local
Generating a RSA private key
...........snip....

$ ls -l
-rw------- 1 shane shane 3272 Jul 20 20:47 demo.site.local.key
-rw-rw-r-- 1 shane shane 2033 Jul 20 20:47 demo.site.local.crt

Key is stored in legacy trusted.gpg keyring

apt-key has been deprecated. Here’s a quick one-liner to fix the annoying message during apt-get update . Ideally, you’d want to pluck out each key using apt-key list then apt-key export <id> placing each key in it’s own file under /etc/apt/trusted.gpg.d.

sudo apt-key --keyring /etc/apt/trusted.gpg exportall | \
sudo tee  /etc/apt/trusted.gpg.d/all_keys.asc

Using cloud-init with SmartOS

SmartOS provides the ability to inject cloud-init data into a zone/VM. This is extremely useful for automating some of the menial tasks one would normally have to perform manually like setting up users, installing packages, or pulling down a git repo. Basically, anything you can stuff into cloud-init user-data is at your disposal.

However, since SmartOS zone definitions are in JSON and cloud-init data is in yaml, it’s not immediately obvious how to supply this information. What it boils down to is, escape all double-quotes (“) and line-feeds.

Here’s our cloud-init config which creates a new user and import their ssh key from launchpad.net.

#cloud-config

users:
  - default
  - name: shaner
    ssh_import_id: shaner
    lock_passwd: false
    sudo: "ALL=(ALL) NOPASSWD:ALL"
    shell: /bin/bash

So following the above escape rules above, here’s our full SmartOS zone spec, including the cloud-init data. Note the cloud-init:user-data key.

{
  "brand": "kvm",
  "alias": "ubuntu-xenial",
  "ram": "2048",
  "vcpus": "2",
  "resolvers": [
    "192.168.1.1",
    "1.1.1.1"
  ],
  "nics": [
    {
      "nic_tag": "admin",
      "ip": "192.168.1.50",
      "netmask": "255.255.255.0",
      "gateway": "192.168.1.1",
      "model": "virtio",
      "primary": true
    }
  ],
  "disks": [
    {
      "image_uuid": "429bf9f2-bb55-4c6f-97eb-046fa905dd03",
      "boot": true,
      "model": "virtio"
    }
  ],
  "customer_metadata": {
    "cloud-init:user-data": "#cloud-config\n\nusers:\n  - default\n  - name: shaner\n    ssh_import_id: shaner\n    lock_passwd: false\n    sudo: \"ALL=(ALL) NOPASSWD:ALL\"\n    shell: /bin/bash"
  }
}

Let’s go ahead and create the zone on our SmartOS box.

[root@vmm01 /opt/templates]# vmadm create < ubuntu-xenial.json
Successfully created VM 0e908925-600a-4365-f161-b3a51467dc08
[root@vmm01 /opt/templates]# vmadm list 
UUID                                  TYPE  RAM      STATE             ALIAS
0e908925-600a-4365-f161-b3a51467dc08  KVM   2048     running           ubuntu-xenial

After a bit of time, we can try logging in as our new user we requested. Recall, we asked cloud-init to pull in our public ssh key from launchpad so, if you get prompted for a password, something is wrong.

shaner@tp25:~$ ssh 192.168.1.50
The authenticity of host '192.168.1.50 (192.168.1.50)' can't be established.
ECDSA key fingerprint is SHA256:hFPjwUJjd7N/Gb9EE37fTVt2Lk6NVzoLKvhFN7wYw2M.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.50' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-116-generic x86_64)
Certified Ubuntu Cloud Image

   __        .                   .
 _|  |_      | .-. .  . .-. :--. |-
|_    _|     ;|   ||  |(.-' |  | |
  |__|   `--'  `-' `;-| `-' '  ' `-'
                   /  ;  Instance (Ubuntu 16.04.3 LTS 20180222)
                   `-'   https://docs.joyent.com/images/linux/ubuntu-certified
                         http://www.ubuntu.com/cloud#joyent

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

shaner@0b8d7a26-ffe4-e859-eb56-d96d02bf213e:~$ sudo ls
shaner@0b8d7a26-ffe4-e859-eb56-d96d02bf213e:~$ sudo apt-update && sudo apt-upgrade -y

There’s a LOT you can do with cloud-init data. See the below links for more info.

Cloud-init examples: https://cloudinit.readthedocs.io/en/latest/topics/examples.html
Joyent Datasource: https://github.com/number5/cloud-init/blob/master/cloudinit/sources/DataSourceSmartOS.py
Joyent Ubuntu Image documentation: https://docs.joyent.com/public-cloud/instances/virtual-machines/images/linux/ubuntu-certified

SmartOS on Alix APU2c2

Over the past few years, I’ve been using SmartOS as my hypervisor of choice coupled with a management layer called Project-Fifo. I have to say, it’s been a joy to work with.

I had a couple Alix APU’s laying around and was curious how well SmartOS would run it.

To begin, I downloaded the SmartOS USB image and pushed onto a USB drive.

wget https://us-east.manta.joyent.com/Joyent_Dev/public/SmartOS/smartos-latest-USB.img.bz2

bzcat smartos-latest-USB.img.bz2 | dd of=/dev/sdb conv=fdatasync

Now,  we can plug the USB drive into the USB port of our APU then power it up. Be sure to plug in your serial cable first so you can see what’s going on.

Soon as you see the GRUB boot menu, press ‘c’ enter the below to switch the console output to ttya from vga. Then hit enter.

variable os_console ttya

After doing the above, you should see something like this

And eventually this. You can now follow along and configure your new SmartMachine.

After networking is all configured, you’ll be prompted to layout a zpool on your disk (hopefully you have an m-sata installed).

Now, just hit enter and be sure to remove the USB drive so SmartOS will boot from the m-sata drive. Eventually, you’ll be presented with the login screen like the below where you can login as root using the password you provided during setup.

Okay, so let’s import a debian dataset and spin up a zone (read: container)

Define the zone config and use vmadm to create it and login!

Cool! A fully functioning Debian 9 container. Let’s setup wordpress and run a load test for funsies.

 

Now, let’s use Siege to perform some load testing

Not Bad!