さわらブログ

さわら(@xhiroga)の技術ブログ

自宅サーバーを構築しました

2021年8月から約9ヶ月をかけて、自宅サーバーを構築しました。

自宅仮想環境

まだまだやることは残っているのですが、とりあえず一区切りということでブログで振り返ります。

TL;DR

以下のような構成です。

自宅サーバー構成

構築にあたってルーター自作PC、ファイルサーバーを全て1から揃え、構成管理のためにAnsibleを新たに学びました。

スケジュールは以下の通りでした。

自宅サーバー スケジュール

当初UbuntuKVMで仮想環境を構築しようとしていたときは先が見えなくて辛かったのですが、偶然にも同僚にProxmoxを教えてもらったことで先が開けました(ありがとうございます) 自分一人では辿り着けなかったのが悔しいですが、土地勘がないジャンルだとこうなるぞという教訓かもしれません。

設定をGitHubで公開する事にこだわった一方で、セキュリティの観点から「隠すべきものは隠す」ことをどう両立するかに頭を悩ませました。 その結果としてGitLabを立てることに思い至ったのですが、これはKubernetesとそのエコシステムをいっぺんに相手にせねばならず、結果挫折しました。

まとめると、早いうちから経験者にレビューしてもらうべきだったなと思います。

動機

簡単にまとめると以下のとおりです。

  • オンプレのインフラを管理したことがなかったのがコンプレックスだった
  • 職場のWindows使いの方が困ったときなどに、手軽に再現できる環境がほしかった
  • Kubernetesなどを試す上で、クラウド上にクラスターを組むと毎月1万円以上かかってしまう
  • ちょっとした用事でLinuxを使いたいときに、いちいちEC2を立ち上げるのがストレス
  • プライベートの開発環境が欲しかったが、会社貸与のMacBook以外にもう一台MacBookを買うのはつまらなかった
  • 趣味の写真やPDF化した漫画などをNASサーバーで管理したかった

アーキテクチャ

私の欲しいものは「仮想環境」と「NASサーバー」に大別されるのですが、それらを一つの筐体にまとめるかがポイントでした。

NASサーバー

結論から言うと仮想環境とNASサーバーは別マシンにし、かつNASサーバーにはSynology NASを選定しました。

マシンをまとめることで場所や電気代が小さくなることが期待された一方で、仮想環境の構築が初めてであったこと、NASサーバーに保存したいデータの重要性から判断しています。

いまでもTrueNASに興味はあるものの、Proxmoxで精一杯なのと、クラウドとの連携やGitなどの機能が搭載されている点から、Synology NASを選んだのは良い判断でした。

仮想環境

ハイパーバイザー型の仮想化を考えていました。XenKVMかではKVMを採用するとして、以下の管理ツールが候補でした。

せっかくならOSSとして貢献できそうなProxmoxを選定。同僚が使っていたのもポイントでした。せっかくなら同じものを使って盛り上がりたいですからね。

ハードウェア

以下のとおりです。しっかり正規価格って感じです。

自作PC ハードウェア

CPUはAPUなのですが、GPUパススルーができるのか今後の課題です。

SSDに関しては、今から買うなら日本製を応援する意味でキオクシアかもしれません。

ソフトウェア管理

Ansibleで管理し、PlaybookとRoleをそれぞれGitHubで公開しています。

構成管理

homelab

github.com

AnsibleのPlaybookを管理しているリポジトリです。GitHubhomelab タグを参考にしました。

RTX1210, Synology NAS, Proxmox, MacbookおよびゲストOSを全て管理しています。ただし、設定を使い回す予定があるものはAnsible Roleに切り出しています。

PoetryとMakefileの併用で、面倒な設定なく動かしやすいのが気に入っています。

ansible-roles

github.com

複数のPlaybookで共有する予定のあるRoleを切り出しました。

特に気に入っているのは、macOSのdefaultsコマンドの実行を自動化し、一部テストも書いた defaults と、開発マシンに必要な設定を詰め込んだ dev です。なお、面倒で Ansible Galaxyには公開していません。

dotfiles

github.com

もう3年近く運用しているmacOSの設定ファイル集です。

Ansibleを学んだことで、動的な設定はAnsible、静的な設定ファイルはdotfilesというように、切り分けがなされました。

自宅サーバーを運用してみて

せっかく仮想環境を作ったにもかかわらず、基本的にはWindowsばかり使っています。

古のプログラムで動かしてみたいものがあるような場合だと、macOSには対応していないこともあるので助かっています。

それ以外だと、(いまやMultipassもありますが)Ubuntuにちょっと入ってBSDとのコマンドの挙動の違いを調べたいときなんかにも便利です。

セキュリティの研究やゲームで活躍してくれるのはこれからですね。

もし時間を巻き戻せるなら...

  • 思い立ってからハードウェア購入までに2ヶ月。時間の方が貴重なので、後でマシン買い直すくらいの勢いでとりあえず始めてしまってもよかったかも
  • 構成図を描いて、経験者の人にアドバイスをもらうべきだった
  • KubernetesとGitLabの導入は当初からスコープ外にすべきだった

一方、時間を巻き戻せるとしても同じようにやるだろう、というのは、

  • Ansibleを前提としてサーバーの設定管理を学んだのは完全に正解。IaCは一番初めから導入すべき。
  • バックアップからの切り戻しは後回しにせず本番前にやるべき

まとめ

9ヶ月かけて自宅サーバーを構築した結果、失敗や迷走も多かったものの、ハードウェアの土地勘やAnsible、Linuxの動かし方を理解することが出来ました。

この環境を使って新たなチャレンジができればと思っています。

AnsibleでWindowsインスタンスを設定してみる(WinRM/ SSH)

TL;DR

Playbookはこちら。

github.com

主な設定を収めたRoleはこちら。

github.com

動機

自宅仮想環境に検証用のWindowsインスタンスを構築しました。

大きく分けると3つのパートからできています。

  1. レジストリの編集
  2. SSH の設定
  3. winget によるアプリケーションのインストール

1. レジストリの編集

正直言ってまだベストが見えていないものの、一旦 role に集約しています。

とりあえず、以下の2点だけ設定しました。

  • 隠しファイルの表示
  • 登録済み拡張子を表示しない設定の無効化

2. SSH の設定

このパートには問題があります。なぜか Ansible WinRM 経由では SSHのインストールが成功しません。仕方ないのでGUIでインストールしています。

ただし、当該処理はSSHで接続しているときはちゃんと流れるんですよね。謎だ...

3. winget によるアプリケーションのインストール

winget によるインストールですが、アプリケーションによっては失敗します(例: Brave)。

こればかりは一つ一つ試すしか無さそうです。

まとめ

Windowsの設定自動化のため、Ansibleを使った設定をしました。

GitHubにはあまり例がなかったので、少しでも後続の方々の参考になればいいなと思います。

Windows 10で固定IPを設定するとインターネットに接続できない → デフォルトゲートウェイもDNSサーバーも、自動では設定されない

TL;DR

検証

デフォルトゲートウェイDNSサーバーが空欄の場合、 ping 8.8.8.8ping google.com も通りません。

デフォルトゲートウェイDNSサーバーが空欄

ping 8.8.8.8 と ping google.com の両方が不通


デフォルトゲートウェイだけ入力してDNSサーバーを空欄にすると、 ping 8.8.8.8 は通るが ping google.com が通りません。

デフォルトゲートウェイだけ入力してDNSサーバーが空欄

ping 8.8.8.8 は通る、ping google.com は通らない


逆に、デフォルトゲートウェイは空欄でDNSサーバーを設定すると、 ping 8.8.8.8ping google.com も通りません。(名前解決も失敗するように見えるのは意外でした)

デフォルトゲートウェイは空欄、DNSサーバーは入力

ping 8.8.8.8 も ping google.com も不通


デフォルトゲートウェイDNSサーバーを設定すると、 ping 8.8.8.8ping google.com も通るようになります

デフォルトゲートウェイDNSサーバーの両方を入力

ping 8.8.8.8 と ping gooogle.com が疎通

まとめ

固定IPの際は、デフォルトゲートウェイDNSサーバーも設定しましょう。

macOSでVPN使用時にプライベートIPアドレスが重複したので、どうすべきだったのかを考える

注意

筆者はネットワークの専門家ではありません。以下で紹介する内容はベストプラクティスではない可能性があります。

経緯

コワーキングスペースから自宅LANにVPN接続したら、自作PC内の仮想環境のマシンに対してSSHができず、はて?となりました。

図で表すとこんな感じです。

VPNでプライベートIPアドレスが重複

いろいろ試した末に原因が分かり、テザリングで接続することでプライベートIPの重複を回避できました。しかし、実際にはどうするのがスマートだったのかを考えます。

問題の切り分け

ping で疎通確認をする、サーバーの電源がONになっているかを確かめる他に、ルーティングテーブルの設定の確認が有効です。

Linuxでは以下のコマンドで、特定のIPアドレスがどのネットワークインターフェース経由でアクセスされるかを知ることができます。

# 仮想ブリッジに接続したLinuxから実行
% ip route get 8.8.8.8
8.8.8.8 via 192.168.100.1 dev vmbr0 src 192.168.100.12 uid 0 
    cache

macOSではコマンドが異なります。

# テザリング + VPN
% route get 192.168.100.12
   route to: 192.168.100.12
destination: 192.168.100.0
       mask: 255.255.255.0
  interface: ppp0
      flags: <UP,DONE,STATIC,PRCLONING>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      1280         0 

# LAN内から実行
% route get 192.168.100.12
   route to: 192.168.100.12
destination: 192.168.100.0
       mask: 255.255.255.0
  interface: en0
      flags: <UP,DONE,CLONING,STATIC>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      1500        -6 

VPN接続時に実行した場合、interfaceが ppp0 になっているのが分かると思います。

これは PPPoE 接続に対応した仮想のネットワークインターフェースらしく、routeがこのインターフェースを通っていればVPNを経由していると考えて良さそうです。

参考

テザリング以外の対策

ルートテーブルを手動または自動で編集し、特定のIPアドレスの場合はVPNのネットワークインターフェースを利用するような設定が考えられます。

それ以外にもNATを使った設定もできるらしいですが、複雑そうなので除外。

参考

まとめ

コワーキングスペースと自宅LANのプライベートIPアドレス空間が重複するという珍しそうな経験をしました。

次回以降はよりスマートに切り分けをしたいところです(もっとも、対応は変わらずテザリングになりそうです)

2022年4月時点での、AWSマネジメントコンソールのアカウントメニューボタン上の文字列の調査

TL;DR

AWS SSOでログインした場合を除き、アカウントエイリアスも表示される。

動機

AWSのマネジメントコンソールのヘッダーの色を自由に変えられるブラウザ拡張を開発・運用しています。

github.com

Issueの改善のために、アカウントメニューボタンの挙動を調べました。

ログイン方法ごとのスクリーンショット

ルートユーザーでログインした場合

アカウントエイリアスが表示されます。

ルートユーザー

IAMユーザーでログインした場合

IAMユーザーの名前 @ アカウントエイリアスが表示されます。

IAMユーザー

IAM Roleを利用している場合

IAM Roleの名前 @ アカウントエイリアスが表示されます。

IAM Role

AWS SSOでログインした場合

Permission Setの名前/ AWS SSOのユーザー名 が表示されます。

AWS SSO

まとめ

AWS SSOでログインした場合を除き、アカウントエイリアスが表示されることが分かりました。

(なお、アカウントエイリアスが設定されていない場合はアカウントIDが表示されるものと思われます)

ProxmoxでWebコンソールからストレージをマウントする(zfs, ext4)

TL;DR

Webコンソールからクラスターを選択し、Disks > ZFS または Disks > Directoryを選び、それぞれ Create: ZFS または Create: Directory で作成することができます。

動機

ターミナルからストレージをマウントしようとすると大変ですよね。パーティションは慎重にやらないといけないし、マウントするパスは迷うし、自動マウントの設定も必要だし...

ProxmoxではWebコンソールからストレージをマウントすることができます。

手順

いずれもクラスター内のメニューから作成できます。なお、DirectoryかZFSかによってマウントパスが違いました。

ZFS の作成

クラスター選択 > Disk > ZFS > Create: ZFS から作成できます。

Create: Directoryのファイルシステムの選択肢にはzfsが無いので注意です。

Create: ZFSを選択

Create: ZFS

ちなみに Kingston の2TB なので k2 という名前でマウントしています。Mount K2に引っ掛けたジョーク... 以降の手順も同様です。

作成時のOutputです。

The operation has completed successfully.
# /sbin/zpool create -o ashift=12 k2 /dev/nvme0n1p1
# /sbin/zfs set compression=on k2
# systemctl enable zfs-import@k2.service
Created symlink /etc/systemd/system/zfs-import.target.wants/zfs-import@k2.service -> /lib/systemd/system/zfs-import@.service.
TASK OK

作成後のWebコンソールと、ターミナルから見たパーティション・マウントパスです。

root@pve:~# lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
nvme1n1     259:0    0 931.5G  0 disk 
|-nvme1n1p1 259:1    0  1007K  0 part 
|-nvme1n1p2 259:2    0   512M  0 part 
`-nvme1n1p3 259:3    0   931G  0 part 
nvme0n1     259:4    0   1.8T  0 disk 
|-nvme0n1p1 259:5    0   1.8T  0 part 
`-nvme0n1p9 259:6    0     8M  0 part
root@pve:~# findmnt
TARGET                        SOURCE           FSTYPE     OPTIONS
/                             rpool/ROOT/pve-1 zfs        rw,relatime,xattr,noacl
|-/sys                        sysfs            sysfs      rw,nosuid,nodev,noexec,relatime
| |-/sys/kernel/security      securityfs       securityfs rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/cgroup            cgroup2          cgroup2    rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/pstore            pstore           pstore     rw,nosuid,nodev,noexec,relatime
| |-/sys/firmware/efi/efivars efivarfs         efivarfs   rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/bpf               none             bpf        rw,nosuid,nodev,noexec,relatime,mode=700
| |-/sys/kernel/debug         debugfs          debugfs    rw,nosuid,nodev,noexec,relatime
| |-/sys/kernel/tracing       tracefs          tracefs    rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/fuse/connections  fusectl          fusectl    rw,nosuid,nodev,noexec,relatime
| `-/sys/kernel/config        configfs         configfs   rw,nosuid,nodev,noexec,relatime
|-/proc                       proc             proc       rw,relatime
| `-/proc/sys/fs/binfmt_misc  systemd-1        autofs     rw,relatime,fd=30,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=33881
|-/dev                        udev             devtmpfs   rw,nosuid,relatime,size=14284768k,nr_inodes=3571192,mode=755,inode64
| |-/dev/pts                  devpts           devpts     rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000
| |-/dev/shm                  tmpfs            tmpfs      rw,nosuid,nodev,inode64
| |-/dev/hugepages            hugetlbfs        hugetlbfs  rw,relatime,pagesize=2M
| `-/dev/mqueue               mqueue           mqueue     rw,nosuid,nodev,noexec,relatime
|-/run                        tmpfs            tmpfs      rw,nosuid,nodev,noexec,relatime,size=2863444k,mode=755,inode64
| |-/run/lock                 tmpfs            tmpfs      rw,nosuid,nodev,noexec,relatime,size=5120k,inode64
| |-/run/rpc_pipefs           sunrpc           rpc_pipefs rw,relatime
| `-/run/user/0               tmpfs            tmpfs      rw,nosuid,nodev,relatime,size=2863440k,nr_inodes=715860,mode=700,inode64
|-/k2                         k2               zfs        rw,xattr,noacl
|-/rpool                      rpool            zfs        rw,noatime,xattr,noacl
| |-/rpool/ROOT               rpool/ROOT       zfs        rw,noatime,xattr,noacl
| `-/rpool/data               rpool/data       zfs        rw,noatime,xattr,noacl
|-/var/lib/lxcfs              lxcfs            fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other
`-/etc/pve                    /dev/fuse        fuse       rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other

ext4, xfs の作成

クラスター選択 > Disk > ZFS > Create: Directory から作成できます。

Create: Directory を選択

Create: Directory

作成時のOutputです。

The operation has completed successfully.
# /sbin/mkfs -t ext4 /dev/nvme0n1p1
mke2fs 1.46.2 (28-Feb-2021)
Discarding device blocks:      4096/488376320  2625536/488376320 79171584/488376320244322304/488376320412094464/488376320                   done                            
Creating filesystem with 488376320 4k blocks and 122101760 inodes
Filesystem UUID: 32b206d1-d332-423f-b49f-e95318530dd7
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
    102400000, 214990848

Allocating group tables:     0/14905           done                            
Writing inode tables:     0/14905           done                            
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information:     0/14905           done

# /sbin/blkid /dev/nvme0n1p1 -o export
Created symlink /etc/systemd/system/multi-user.target.wants/mnt-pve-k2.mount -> /etc/systemd/system/mnt-pve-k2.mount.
TASK OK

作成後のWebコンソールと、ターミナルから見たパーティション・マウントパスです。

Directories

root@pve:~# lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
nvme1n1     259:0    0 931.5G  0 disk 
|-nvme1n1p1 259:1    0  1007K  0 part 
|-nvme1n1p2 259:2    0   512M  0 part 
`-nvme1n1p3 259:3    0   931G  0 part 
nvme0n1     259:4    0   1.8T  0 disk 
|-nvme0n1p1 259:5    0   1.8T  0 part /mnt/pve/k2
`-nvme0n1p9 259:6    0     8M  0 part 
TARGET                        SOURCE           FSTYPE     OPTIONS
/                             rpool/ROOT/pve-1 zfs        rw,relatime,xattr,noacl
|-/sys                        sysfs            sysfs      rw,nosuid,nodev,noexec,relatime
| |-/sys/kernel/security      securityfs       securityfs rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/cgroup            cgroup2          cgroup2    rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/pstore            pstore           pstore     rw,nosuid,nodev,noexec,relatime
| |-/sys/firmware/efi/efivars efivarfs         efivarfs   rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/bpf               none             bpf        rw,nosuid,nodev,noexec,relatime,mode=700
| |-/sys/kernel/debug         debugfs          debugfs    rw,nosuid,nodev,noexec,relatime
| |-/sys/kernel/tracing       tracefs          tracefs    rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/fuse/connections  fusectl          fusectl    rw,nosuid,nodev,noexec,relatime
| `-/sys/kernel/config        configfs         configfs   rw,nosuid,nodev,noexec,relatime
|-/proc                       proc             proc       rw,relatime
| `-/proc/sys/fs/binfmt_misc  systemd-1        autofs     rw,relatime,fd=30,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=33881
|-/dev                        udev             devtmpfs   rw,nosuid,relatime,size=14284768k,nr_inodes=3571192,mode=755,inode64
| |-/dev/pts                  devpts           devpts     rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000
| |-/dev/shm                  tmpfs            tmpfs      rw,nosuid,nodev,inode64
| |-/dev/hugepages            hugetlbfs        hugetlbfs  rw,relatime,pagesize=2M
| `-/dev/mqueue               mqueue           mqueue     rw,nosuid,nodev,noexec,relatime
|-/run                        tmpfs            tmpfs      rw,nosuid,nodev,noexec,relatime,size=2863444k,mode=755,inode64
| |-/run/lock                 tmpfs            tmpfs      rw,nosuid,nodev,noexec,relatime,size=5120k,inode64
| |-/run/rpc_pipefs           sunrpc           rpc_pipefs rw,relatime
| `-/run/user/0               tmpfs            tmpfs      rw,nosuid,nodev,relatime,size=2863440k,nr_inodes=715860,mode=700,inode64
|-/mnt/pve/k2                 /dev/nvme0n1p1   ext4       rw,relatime
|-/rpool                      rpool            zfs        rw,noatime,xattr,noacl
| |-/rpool/ROOT               rpool/ROOT       zfs        rw,noatime,xattr,noacl
| `-/rpool/data               rpool/data       zfs        rw,noatime,xattr,noacl
|-/var/lib/lxcfs              lxcfs            fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other
`-/etc/pve                    /dev/fuse        fuse       rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other

間違って作成した場合

ZFSとDirectoryどちらの場合でも、選択して More から Destroy を選ぶことで削除が可能です。

ZFS の削除

ZFS Pool k2 - Remove

Removed /etc/systemd/system/zfs-import.target.wants/zfs-import@k2.service.
wiping block device /dev/nvme0n1p1
/dev/nvme0n1p1: 8 bytes were erased at offset 0x0003b000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x00029000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x00028000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x0007b000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x00069000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x00068000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x00066000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x00065000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x00064000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07bb000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07a9000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07a8000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07a6000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07a5000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07a4000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07fb000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07e9000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07e8000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07e6000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07e5000 (zfs_member): 0c b1 ba 00 00 00 00 00
/dev/nvme0n1p1: 8 bytes were erased at offset 0x1d1c07e4000 (zfs_member): 0c b1 ba 00 00 00 00 00
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0.189003 s, 1.1 GB/s
The operation has completed successfully.
TASK OK

ext4, xfs の削除

Directory k2 - Remove

Removed /etc/systemd/system/multi-user.target.wants/mnt-pve-k2.mount.
wiping block device /dev/nvme0n1p1
/dev/nvme0n1p1: 2 bytes were erased at offset 0x00000438 (ext4): 53 ef
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0.33387 s, 628 MB/s
The operation has completed successfully.
TASK OK

まとめ

増設したSSDをマウントすることができました。

NestJS Meetup Online #1を振り返って【アンケート分析】 #nestjs_meetup

NestJS Meetup運営のさわらです。

2022年3月18日にNestJS Meetup Online #1が開催されました!

nest-jp.connpass.com

Connpassでは約150名が登録、Youtube Liveは200名以上が視聴し、第一回としては成功と言えたのではないでしょうか。

本記事では第一回の様子を、Connpass、YouTubeGoogle Formのアンケートの3つから振り返ります。

ちなみに第二回はこちらからご参加いただけます!

nest-jp.connpass.com

TL;DR

  • まだまだイベントの存在を知らない人はいる。Connpassを使い倒して参加者を広げるべき
  • YouTubeアーカイブを見る人向けの配信画面の工夫を
  • 初心者〜上級者まで幅広く楽しいイベント内容に

Connpass

Connpassからは、イベント参加者の方がどんな媒体から登録してくださったかが分かります。

大まかに言って、Connpassからの流入4割・Twitterからの流入3割・その他がダイレクトやGoogle検索など、と見られます。

ページビューとユニークユーザーが比例しているのも面白いですね。「そんなイベントやってたんだ!?今知った!」というような、イベントを知らない人がまだまだいることが予想されます。

f:id:hiroga_cc:20220408213631p:plain
NestJS meetup Online #1 イベント統計

公開直後かイベント直前かでも流入経路が違います。公開直後はTwitterが最大の割合を占めています。

f:id:hiroga_cc:20220408213727p:plain
NestJS meetup Online #1 公開直後

しかし、当日が近づくとConnpassからの流入が増えることが分かります。また、Google検索から来る人がいることも伺えます。

f:id:hiroga_cc:20220408213808p:plain
NestJS meetup Online #1 開催当日まで

これらの分析結果から、以下のような洞察が得られるかもしれません。

  • イベント公開後はTwitterで告知をすべき。Google検索で上位にインデックスされる可能性も高まる。
  • Connpassからの流入は思った以上にあるため、イベントページにキーワードを配置するなどのConnpass向けSEOや、前回参加者への次回イベント告知メール送信などは有効である。
  • 統計を確認してユニークユーザーの伸びが頭打ちになるまでは告知に注力するべき。

YouTube Live

YouTube Studioでは、ライブ放送の分析を見ることができます。

Meetupの最大同時接続数は66人で、Connpass参加者の46%でした。また、当日以降もアーカイブが視聴され続けています。

イベント中は大きな人数の変動はなく、多くの参加者がイベントを視聴し続けてくださったことが分かります。

f:id:hiroga_cc:20220408215434p:plain
NestJS Meetup Online #1 YouTube Live

一方でチャットは登壇の開始・終了に限定され、ハッシュタグでのツイートのほうが優勢であることが伺えます。

StreamYardの設定次第ですが、ハッシュタグのツイートを画面に表示するようにすると、後から視聴する人がよりライブ感を楽しめるかもしれませんね。

思い切ってYouTube Liveのチャット欄を閉じてしまうのもいいかもしれません。

f:id:hiroga_cc:20220408220101p:plain
NestJS meetup Online #1 YouTube Live チャットメッセージ

Google Form アンケート

イベント後のアンケートには、29名の方が回答してくださいました。

NestJSとの関わりですが、仕事で利用している方が50%を超えている結果となりました。

個人的にそこまで普及しているのかと驚きました。また、次回アンケートでは詳細な技術スタック(エンジンやORMなど、NestJS周辺技術)についても聞いてみてもいいかもしれません。

f:id:hiroga_cc:20220408220400p:plain
NestJS meetup Online #1 NestJSとの関わり

参加者の職種としてはフルスタックエンジニアが半数以上となりました。NestJSらしい結果であると思います。

これを受けて、Connpassのページにフロントエンド向け・フルスタック向けのキーワードを散らすのもいいかもしれません(Next.js、モノリポ、etc...)

f:id:hiroga_cc:20220408220634p:plain
NestJS meetup Online #1 あなたの職種

一方でLTの満足度は4が最も多く、改善の余地が伺えます。

アンケートの感想には、理解できない部分が多かった、スライドの見づらさ、もっと色々な話を聞きたい、という要望が見られました。

#1 では登壇者が2名だけだったので、 #2 以降のイベントでは登壇者を増やし、内容も初心者〜上級者まで幅広く取るといいかもしれません。

例えば「なぜNestJSを選定したか?」などは、NestJSへの習熟度とは無関係に楽しめますね!

f:id:hiroga_cc:20220408220832p:plain
NestJS meetup Online #1 LTの満足度

まとめ

初のオンライン開催ということで手探り状態でしたが、多くの方に刺激を与えることができたのは良かったと思います。

#1 の反省を #2 で活かし、より良いイベントにしていきましょう!

#2 の登録は以下から行えます。ぜひご参加くださいませ!

nest-jp.connpass.com