🦔

UTMを使って、macOS上でArch Linux ARMを動かす

2024/09/17に公開

macOSの仮想ソフトとして、筆者はParallels Toolsを使っていたのですが、ホストとファイルを共有しようとしてParallel Toolsをインストールしてみようとしたところ、python2に依存していたりして使いたくなくなったので、UTMを試してみました。

筆者の環境:

  • Apple M3 Max
  • macOS Sonoma 14.4.1
  • UTM Version 4.5.4

公式のGalleryにArch Linuxのインストール済みイメージがあるのでそれを使いました。また、ssh越しに操作する方が楽なので、できるだけ早くsshで操作できるような手順にしておきました。

  1. UTMをインストールします。https://mac.getutm.app/ からダウンロードしてインストールするか、brew caskでインストールします。

    $ brew install --cask utm
    
  2. UTMのGalleryから、ArchLinux ARMを選び、Open in UTMをクリックします。

  3. rootのパスワードはデフォルトでrootになっているので、ログインしてrootのパスワードを更新します。

    alarm login: root
    Password: root
    # passwd
    
  4. mirrorlistで、Japanを選択します。

    # nano /etc/pacman.d/mirrorlist
    
    --- /etc/pacman.d/mirrorlist.orig	2024-09-15 16:29:06.295402722 +0000
    +++ /etc/pacman.d/mirrorlist	2024-09-15 16:30:07.834829056 +0000
    @@ -4,7 +4,7 @@
     #
    
     ## Geo-IP based mirror selection and load balancing
    -Server = http://mirror.archlinuxarm.org/$arch/$repo
    +# Server = http://mirror.archlinuxarm.org/$arch/$repo
    
     ### Mirrors by country
    
    @@ -41,7 +41,7 @@
    
     ### Japan
     ## Tokyo
    -# Server = http://jp.mirror.archlinuxarm.org/$arch/$repo
    +Server = http://jp.mirror.archlinuxarm.org/$arch/$repo
    
     ### Singapore
     # Server = http://sg.mirror.archlinuxarm.org/$arch/$repo    
    
  5. パッケージを最新に更新します。

    # pacman -Syu
    ...
    :: Proceed with installation? [Y/n] Y
    

    FIXME: なお、この際に以下のエラーが出ます。/bootがdisk fullになっていますが、普通のinitramfsは無事生成できていて、fallbackのinitramfsの生成ができていない状態なので、とりあえずは使えます。ただ非常に気持ち悪いので、後で/bootを増やして追記する予定です。

    error: Partition /boot too full: 2558 blocks needed, 0 blocks free
    error: not enough free disk space
    error: failed to commit transaction (not enough free disk space)
    Errors occurred, no packages were upgraded.
    
  6. sudoをインストールします。

    # pacman -S sudo
    ...
    :: Proceed with installation? [Y/n] Y
    
  7. wheelsudoを許可します。

    # nano /etc/sudoers 
    
    --- /etc/sudoers.orig	2024-09-15 16:41:59.269846570 +0000
    +++ /etc/sudoers	2024-09-15 16:01:56.285753081 +0000
    @@ -111,7 +111,7 @@
     root ALL=(ALL:ALL) ALL
    
     ## Uncomment to allow members of group wheel to execute any command
    -# %wheel ALL=(ALL:ALL) ALL
    +%wheel ALL=(ALL:ALL) ALL
    
     ## Same thing without a password
     # %wheel ALL=(ALL:ALL) NOPASSWD: ALL
    
  8. 作業用のアカウントを作ります。(仮にユーザー名はuserとしますが、もちろん自由に変えて構いません)

    # useradd -m user
    # usermod -a -G wheel user
    # passwd user
    
  9. hostnameを設定します。(仮にここではデフォルトのalarmを使ったことにしますが、もちろん自由に変えて構いません)

    # nano /etc/hostname
    
  10. mDNSを有効にして、alarm.localでhostから繋げるようにします。

    # nano /etc/systemd/network/en.network
    
    --- /etc/systemd/network/en.network.orig	2024-09-15 16:39:48.478968011 +0000
    +++ /etc/systemd/network/en.network	2024-09-15 15:55:24.295853037 +0000
    @@ -4,3 +4,4 @@
     [Network]
     DHCP=yes
     DNSSEC=no
    +MulticastDNS=yes
    
  11. rebootします。

    # reboot
    
  12. この段階でhostからsshできるようになっているはずです。hostから以下を実行します。ただし、sshの秘密鍵の生成およびssh-agentの設定は事前にしておいてください。

    $ ssh-copy-id user@alarm.local
    $ ssh user@alarm.local -A
    
  13. sshでのパスワードログインを禁止します。

    $ sudo nano /etc/ssh/sshd_config
    
    --- /etc/ssh/sshd_config.orig	2024-09-15 16:52:41.194449621 +0000
    +++ /etc/ssh/sshd_config	2024-09-15 16:53:07.002792302 +0000
    @@ -55,7 +55,7 @@
     #IgnoreRhosts yes
    
     # To disable tunneled clear text passwords, change to no here!
    -#PasswordAuthentication yes
    +PasswordAuthentication no
     #PermitEmptyPasswords no
    
     # Change to no to disable s/key passwords
    
  14. timezoneの設定をします。

    $ sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
    
  15. localeの設定をします。

    $ sudo nano /etc/locale.gen
    
    --- /etc/locale.gen.orig	2024-09-16 02:11:02.483375293 +0900
    +++ /etc/locale.gen	2024-09-16 02:11:29.616496548 +0900
    @@ -168,7 +168,7 @@
     #en_SC.UTF-8 UTF-8
     #en_SG.UTF-8 UTF-8
     #en_SG ISO-8859-1
    -en_US.UTF-8 UTF-8
    +#en_US.UTF-8 UTF-8
     #en_US ISO-8859-1
     #en_ZA.UTF-8 UTF-8
     #en_ZA ISO-8859-1
    
    $ sudo locale-gen
    $ sudo nano /etc/locale.conf
    
    diff -u /etc/locale.conf.orig /etc/locale.conf
    --- /etc/locale.conf.orig	2024-09-16 02:14:48.740863401 +0900
    +++ /etc/locale.conf	2024-09-16 02:14:40.455793945 +0900
    @@ -1 +1 @@
    -LANG=C
    +LANG=en_US.UTF-8
    
  16. rustupをインストールします。

    $ sudo pacman -S rustup
    ...
    :: Proceed with installation? [Y/n] Y
    $ rustup default stable
    
  17. paruをインストールします。

    $ sudo pacman -S --needed base-devel clang git
    ...
    :: Proceed with installation? [Y/n] Y
    $ git clone https://aur.archlinux.org/paru.git
    $ cd paru
    

    ただし、ここで https://github.com/Morganamilo/paru/issues/1154#issuecomment-2002357898 のパッチを当てます。当てないとコンパイルエラー[1]になります。

    $ nano PKGBUILD
    
    --- PKGBUILD.orig	2024-09-15 17:02:27.109811081 +0000
    +++ PKGBUILD	2024-09-15 17:02:40.927952547 +0000
    @@ -29,6 +29,10 @@
         export CARGO_PROFILE_RELEASE_LTO=off
       fi
    
    +  if [[ $CARCH = aarch64 ]]; then
    +    _features+="generate,"
    +  fi
    +
       cargo build --frozen --features "${_features:-}" --release --target-dir target
       ./scripts/mkmo locale/
     }
    
    $ makepkg -si
    
脚注
  1. コンパイルエラーの内容は以下の通りです。

    error[E0308]: mismatched types
       --> /home/user/.cargo/git/checkouts/alpm.rs-a0070a235cf20bfa/306342e/alpm/src/cb.rs:244:60
        |
    244 |         unsafe { alpm_option_set_logcb(self.as_ptr(), Some(cb), &*ctx as *const _ as *mut _) };
        |                                                       ---- ^^ expected fn pointer, found fn item
        |                                                       |
        |                                                       arguments to this enum variant are incorrect
        |
        = note: expected fn pointer `unsafe extern "C" fn(_, _, _, *mut __va_list_tag)`
                      found fn item `extern "C" fn(_, _, _, [__va_list_tag; 1]) {logcb::<LogCbImpl<T, F>>}`
    help: the type constructed contains `extern "C" fn(*mut c_void, u32, *const u8, [__va_list_tag; 1]) {logcb::<LogCbImpl<T, F>>}` due to the type of the argument passed
       --> /home/sunaemon/.cargo/git/checkouts/alpm.rs-a0070a235cf20bfa/306342e/alpm/src/cb.rs:244:55
        |
    244 |         unsafe { alpm_option_set_logcb(self.as_ptr(), Some(cb), &*ctx as *const _ as *mut _) };
        |                                                       ^^^^^--^
        |                                                            |
        |                                                            this argument influences the type of `Some`
    note: tuple variant defined here
       --> /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/option.rs:582:5
    
    ↩︎

Discussion