POTATOSIPS STARPORT

ARCHAZURE

VIRTUAL MACHINE DEPLOYMENT PROTOCOL // BIOS MODE // ORACLE VIRTUALBOX
Oracle VirtualBox
30GB Fixed VHD
Bridge Networking
BIOS Mode
Azure CLI
SYS-00

VirtualBox Setup

Oracle VirtualBox
BIOS Mode — NOT EFI
30GB Fixed VHD
1
Download VirtualBox. It's free. It's cursed. It's yours.

virtualbox.org — Downloads

archlinux.org — Download the ISO

Download the latest Arch Linux ISO. It is a rolling release, which means it is always up to date and also always slightly different from the last time you used it.
2
Create a new VM. Name it something professional. Or don't.

Open VirtualBox → New → set the following:

SettingValue
NameAzureVmTemplate (or whatever haunts you)
TypeLinux
VersionArch Linux (64-bit)
RAM2048 MB minimum
3
Create a 30GB fixed-size VHD disk. Fixed, not dynamic. Azure is picky.

When prompted for storage: choose Create a virtual hard disk nowVHD (Virtual Hard Disk)Fixed size30 GB.

Use VHD format, not VDI or VMDK. Azure only accepts VHD. Ask Azure why. It won't answer.
4
⚠ Disable EFI. This is not optional. This is survival.

Go to Settings → System → Motherboard.

Make sure "Enable EFI (special OSes only)" is unchecked. GRUB will be installed in BIOS/MBR mode. EFI will cause everything to collapse quietly and without mercy.

🚫 EFI = DEATH

If EFI is enabled, the GRUB install will appear to succeed, the VM will appear to boot, and then nothing will work in Azure. You will spend hours debugging something that a single unchecked checkbox caused. Uncheck it now. Sleep well later.

5
Enable bridge networking for SSH access.

Go to Settings → Network → Adapter 1 → set Attached to: Bridged Adapter → select your active network interface.

Bridged mode puts the VM on your actual network. You'll be able to SSH in from your host. NAT also works but you'll need port forwarding and the energy to set it up.
6
Mount the Arch ISO and boot.

Go to Settings → Storage → Controller: IDE → click the empty optical drive → Choose a disk file → select the Arch ISO.

Start the VM. You will be dropped into a root shell. You are now on the launchpad.

SYS-01

Arch Linux Installation

Boot from ISO
BIOS Mode Active
Target: /dev/sda
1
Sync the clock. The universe won't wait.
CHRONO-SYNC
$ timedatectl set-ntp true
2
Partition the disk. Choose carefully — there's no undo in the void.
DISK SURGERY
$ cfdisk /dev/sda
PartitionSizeTypePurpose
/dev/sda110 MBBIOS bootGRUB anchor point
/dev/sda2RemainingLinux filesystemEverything else. Your whole life.
3
Format and mount. It's not destruction, it's reallocation of entropy.
FORMAT + MOUNT
$ mkfs.ext4 /dev/sda2
$ mount /dev/sda2 /mnt
4
Install the base system. This is the moment of no return.
PACSTRAP SEQUENCE
$ pacstrap /mnt base linux linux-firmware grub nano git \
    btop curl wget openssh dhcpcd sudo dnsutils \
    base-devel htop
5
Generate fstab. Let the machine know where it lives.
FSTAB GENERATION
$ genfstab -U /mnt >> /mnt/etc/fstab
6
Chroot in. You are now inside the machine. Breathe.
CHROOT
$ arch-chroot /mnt
7
Set timezone and hardware clock. Dhaka Standard Time. Respectable.
TIMEZONE + CLOCK
$ ln -sf /usr/share/zoneinfo/Asia/Dhaka /etc/localtime
$ hwclock --systohc
8
Configure locale. Because the system needs to know which language to fail in.
LOCALE CONFIG
$ nano /etc/locale.gen  # Uncomment: en_US.UTF-8 UTF-8
$ locale-gen
$ echo "LANG=en_US.UTF-8" > /etc/locale.conf
$ echo "KEYMAP=us" > /etc/vconsole.conf
9
Install GRUB. The bootloader that has outlived careers.
BOOTLOADER INSTALL
$ grub-install --target=i386-pc /dev/sda
$ nano /etc/default/grub  # Edit if needed
$ grub-mkconfig -o /boot/grub/grub.cfg
10
Set root password. Make it something you'll forget at 3 AM.
ROOT ACCESS
$ passwd
11
Create a user. Name it whatever. It won't judge you.
USER CREATION
$ useradd -m -G wheel -s /bin/bash potato
$ passwd potato
Replace potato with your preferred username. Or don't. Potato is a perfectly valid identity.
12
Edit sudoers. Grant the wheel. Accept the power. Fear it.
SUDOERS
$ nano /etc/sudoers
# Uncomment both wheel lines:
# %wheel ALL=(ALL:ALL) ALL
# %wheel ALL=(ALL:ALL) NOPASSWD: ALL
13
Configure SSH and enable services.
SSH + SERVICES
$ nano /etc/ssh/sshd_config  # Set PermitRootLogin yes
$ systemctl enable dhcpcd
$ systemctl enable sshd
14
Set up /etc/hosts. Introduce the machine to itself.
/ETC/HOSTS
$ nano /etc/hosts
# Add:
127.0.0.1    localhost
::1          localhost
127.0.1.1    AzureVmTemplate AzureVmTemplate.localdomain
15
Exit chroot, unmount, power off. The first phase is complete.
POWER DOWN
$ exit
$ umount -a
$ poweroff
SYS-02

Prepare for Azure

⚡ BOOT FIRST

Boot the VM after the initial installation before proceeding. The following steps run inside the live system, not the installer.

1
Add Hyper-V kernel modules. Azure runs on Hyper-V. Resistance is futile.
MKINITCPIO
$ nano /etc/mkinitcpio.conf
# Change:
MODULES=(hv_storvsc hv_vmbus)
REBUILD INITRAMFS
$ mkinitcpio -p linux
SYS-03

WA Linux Agent

1
Switch user and clone walinuxagent from AUR. Because of course it's from AUR.
AUR CLONE
$ su potato
$ cd && mkdir aur && cd aur
$ git clone https://aur.archlinux.org/walinuxagent.git
$ cd walinuxagent && makepkg -si
2
Enable waagent. Let Azure's watchdog keep its eye on you.
ENABLE WAAGENT
$ systemctl enable waagent
3
Configure waagent swap. Give Azure its resource disk back.
WAAGENT CONFIG
$ nano /etc/waagent.conf
# Set:
ResourceDisk.EnableSwap=y
ResourceDisk.SwapSizeMB=8192
RESOURCE MOUNT
$ mkdir /mnt/resource
4
Clean up. Leave no trace. You were never here.
CLEANUP
$ rm -Rf ~/.bash_history ~/aur
5
Deprovision. This is the last thing the VM remembers.
DEPROVISION + SHUTDOWN
$ waagent -force -deprovision
$ export HISTSIZE=0
$ shutdown -h now
SYS-04

Upload to Azure

1
Install Azure CLI. Follow the official docs — they change it every few months just to keep you humble.

learn.microsoft.com — Install Azure CLI

2
Login. Let Microsoft know you've accepted defeat.
AZ LOGIN
$ az login
3
Upload the VHD. The final act. The thing all of this was for.
BLOB UPLOAD
$ az storage blob upload \
    --account-name <storage-account-name> \
    --account-key  <access-key> \
    --container-name <container-name> \
    --name arch.vhd \
    --file <path/to/your.vhd>
Replace all <bracketed> values with your actual Azure credentials. Do not commit them to git. Do not paste them in Discord. You know what you did last time.
✓ TRANSMISSION COMPLETE

Your Arch Linux VHD is now floating somewhere in Microsoft's data centers. It has survived VirtualBox, a manual partition table, GRUB in BIOS mode, and the Azure provisioning process. Respect it accordingly.