Open28

環境構築を支える技術

gtnaogtnao

自分はEC2で使い捨ての真っ新なUbuntuを立てては破棄してを繰り返して遊ぶことが多い
Neovim,zsh,tmuxあたりはdotfiles化しているが、各種言語/ツールのインストールは毎回コマンドを叩いたり、プロジェクト作成/Formatter&Linterのデファクトな方法などを毎回調べたりで面倒臭いのでまとめる
例えば最近だと、LLMで遊びたいけどPythonのプロジェクトってどうやって作るのが主流だっけ?Poetryだったはずだが?(最近また新しいのが出たとか聞いた)とか、普段使いじゃない言語だと特に

gtnaogtnao

まずは、AWS EC2を立てる
毎回マネコンをポチってて良い加減面倒なので、
TerraformでVPCなどを含めて作成できるようにしておきたいので、そこからやる

gtnaogtnao

GHAでOIDCでterraform applyしたいので、まずはその準備
以下はCloudShellで行う(こんな手軽なものがあったのか)

IAM identity providersの作成

aws iam create-open-id-connect-provider \
  --url https://token.actions.githubusercontent.com \
  --client-id-list sts.amazonaws.com

IAM roleの作成
適宜<>を置き換え

cat <<EOF > trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:<OWNER>/<REPOSITORY>:*"
        },
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
EOF

aws iam create-role \
  --role-name GitHubActionTerraformRole \
  --assume-role-policy-document file://trust-policy.json

// 本来はもっと限定すべき
aws iam attach-role-policy \
  --role-name GitHubActionTerraformRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

aws iam attach-role-policy \
  --role-name GitHubActionTerraformRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonVPCFullAccess

aws iam attach-role-policy \
  --role-name GitHubActionTerraformRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess

state保存用のS3 bucketの作成

aws s3api create-bucket \
  --bucket <BUCKET_NAME> \
  --region ap-northeast-1 \
  --create-bucket-configuration LocationConstraint=ap-northeast-1
gtnaogtnao

まず、key pairを作成しておく
これもCloudShellで行う

aws ec2 create-key-pair \
  --key-name <KEY_NAME> \
  --query 'KeyMaterial' \
  --output text

標準出力に秘密鍵が吐かれるので、コピってローカルに保存しておく

chmod 400 <sandbox.pem>
gtnaogtnao

Ubuntu 24.04の最新のAMIのIDを知るコマンド
これもCloudShellで叩く

aws ec2 describe-images \
  --region ap-northeast-1 \
  --owners "099720109477" \
  --filters "Name=name,Values=ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*" \
  --query "sort_by(Images, &CreationDate)[-1].ImageId" \
  --output text

(追記)
tfファイル内でもできそうなのでそちらに書いておく

gtnaogtnao

EC2立ち上げるだけで結構費やしてしまった
仕事ならもっとセキュアにやった方が良い箇所もあるが一旦これで

gtnaogtnao

現在のdotfilesは
https://github.com/gtnao/dotfiles
年末にnvimの設定だけ見直ししていて、init.lua1ファイルにまとめている(途中)
https://github.com/gtnao/init.lua

bash -c "$(wget -O- https://raw.githubusercontent.com/gtnao/dotfiles/main/install.sh)"

を叩けば前者の環境が結構ちゃんと構築されるようになっているが、
一旦色々見直したいので使わずに検討する

gtnaogtnao

さて、SSHログインしたEC2内で色々入れていく

まずは

sudo apt update
sudo apt -y upgrade

絶対に必須そうなものを入れる
wget/curl/gitとかは入っているかもだが念為
unzipは入ってなくてコケることが多いので重要

sudo apt -y install \
  wget curl git \
  unzip \
  build-essential
gtnaogtnao

まず、入れたいものを洗い出す(適宜更新)

言語

メイン

  • C/C++
    • build-essentialを入れたので既にコンパイルできる
  • Rust
  • Golang
  • Java
  • Node
  • Ruby
  • Python

サブ

ツール

DevOps系

  • docker
  • k8s
  • terraform
  • クラウド(AWS/GoogleCloud)のCLI

Local系

  • Neovim
  • zsh
  • tmux
  • ripgrep
  • ghq
gtnaogtnao

コードを書くにはNeovim環境を整えないとどうしようもないので、そこから
Neovimは最新バージョンを入れたいので、GitHubから落としてくる

NEOVIM_VERSION=0.10.3
curl -LO "https://github.com/neovim/neovim/releases/download/v${NEOVIM_VERSION}/nvim.appimage"
chmod u+x nvim.appimage
./nvim.appimage --appimage-extract
sudo mkdir -p /opt/neovim
sudo mv squashfs-root /opt/neovim/
sudo ln -s /opt/neovim/squashfs-root/usr/bin/nvim /usr/local/bin/nvim
rm nvim.appimage

Ref

gtnaogtnao

ghqを入れてgitリポジトリ管理をしたい
ghqを入れるためにGolangを入れる

Golang

wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz
rm go1.23.4.linux-amd64.tar.gz

/usr/local/go/bin以下にgoがあるのでパスを通す
~/go/bin

echo 'export PATH="/usr/local/go/bin:${PATH}"' >> ~/.bashrc
echo 'export PATH="${HOME}/go/bin:${PATH}"' >> ~/.bashrc

bash以外に変えるつもりだが一旦全部パスはbashrcに書いて通すこととする

ghq

go install github.com/x-motemen/ghq@latest

Ref

gtnaogtnao

https://github.com/gtnao/init.lua
をghqでcloneして、init.luaはこっちのsymlinkを使うようにする。
と、その前に、ssh鍵を作ってGitHubに登録しないと怒られる

ghq get git@github.com:gtnao/init.lua.git
ln -sf "${HOME}/ghq/github.com/gtnao/init.lua/init.lua" ~/.config/nvim/init.lua

SSH

ssh-keygen -t rsa -b 2048 -f "${HOME}/.ssh/id_rsa" -N ""
chmod 600 "${HOME}/.ssh/id_rsa"
chmod 644 "${HOME}/.ssh/id_rsa.pub"
cat "${HOME}/.ssh/id_rsa.pub"

GitHubに登録しておく
https://github.com/settings/ssh/new

gtnaogtnao

各種言語の開発に必要なものを入れていく

C,C++

  • build-essentialが入っているので最低限コンパイルできる
  • CMakeを入れる
  • Bazelも入れておく
sudo apt -y install cmake

sudo apt install apt-transport-https curl gnupg -y
curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor >bazel-archive-keyring.gpg
sudo mv bazel-archive-keyring.gpg /usr/share/keyrings
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
sudo apt update && sudo apt -y install bazel

Ref

方針メモ

  • CMakeは枯れているのでaptでOK
  • Bazelはよう分からんが、よう分からんものはとりあえずaptで
  • asdfを使うのは言語の処理系とかプロジェクトごとにバージョンをちょこちょこ変える必要があるものとする
  • 自前でビルドしたりバイナリ取ってきたりするのは最新バージョンにこだわりがあるものとする
    • eg. Neovim
gtnaogtnao

以下、ホームディレクトリにsandboxディレクトリを切ってその中のサブディレクトリで試す

mkdir sandbox
cd sandbox
mkdir <hoge_sandbox>

随時必要なLSPやTreesitterはinit.luaに書き足していく

CMakeことはじめ

CMakeLists.txt
cmake_minimum_required(VERSION 3.28)
project(CmakeSandbox)

add_executable(main main.cpp)
mkdir build
cd build
cmake ..
make
./main

Bazelことはじめ

WORKSPACE
workspace(name = "my_project")
BUILD
cc_binary(
    name = "main",
    srcs = ["main.cpp"],
)
bazel build //:main
./bazel-bin/main

Treesitterはstarlark

gtnaogtnao

asdfを入れる

git clone https://github.com/asdf-vm/asdf.git "${HOME}/.asdf" --branch "master"
echo '. "${HOME}/.asdf/asdf.sh"' >> ~/.bashrc
gtnaogtnao

Python

asdf

https://github.com/asdf-community/asdf-python
https://github.com/pyenv/pyenv/wiki#suggested-build-environment

version

https://devguide.python.org/versions/

sudo apt -y install build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl git \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
asdf plugin-add python https://github.com/asdf-community/asdf-python.git
asdf install python 3.13.1
asdf global python 3.13.1
gtnaogtnao

Ruby

asdf

https://github.com/asdf-vm/asdf-ruby?tab=readme-ov-file
https://github.com/rbenv/ruby-build/wiki#suggested-build-environment

version

https://www.ruby-lang.org/ja/downloads/releases/

sudo apt -y install autoconf patch build-essential rustc libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev
asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git
asdf install ruby 3.4.1
asdf global ruby 3.4.1
gtnaogtnao

Rust

https://www.rust-lang.org/ja/tools/install
Rustは一発

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

のはずだったが、

warning: it looks like you have an existing installation of Rust at:
warning: /usr/bin
warning: It is recommended that rustup be the primary Rust installation.
warning: Otherwise you may have confusion unless you are careful with your PATH
warning: If you are sure that you want both rustup and your already installed Rust
warning: then please reply y' or yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yes
warning: or pass `-y' to ignore all ignorable checks.
error: cannot install while Rust is installed
warning: continuing (because the -y flag is set and the error is ignorable)

と出てしまう
rustcだけ既に入っている

sudo apt -y remove rustc
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \
  --default-toolchain stable \
  --no-modify-path
  -y
echo '. "${HOME}/.cargo/env"' >> ~/.bashrc
gtnaogtnao

Docker

https://docs.docker.com/engine/install/ubuntu/

# Add Docker's official GPG key:
sudo apt update
sudo apt -y install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update

sudo apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo無しで実行できるようにdocker groupに入れる
https://docs.docker.com/engine/install/linux-postinstall/

sudo usermod -aG docker $USER
newgrp docker
gtnaogtnao

aquaを入れてk8s系のツールを試せるようにしておく
https://aquaproj.github.io/docs/install

Golangが既に入っているのでgo getで

go install github.com/aquaproj/aqua/v2/cmd/aqua@latest
echo 'export PATH="$(aqua root-dir)/bin:$PATH"' >> ~/.bashrc
gtnaogtnao

Terraform

terraformはasdfで入れる

asdf

https://github.com/asdf-community/asdf-hashicorp

asdf plugin-add terraform https://github.com/asdf-community/asdf-hashicorp.git
asdf install terraform 1.10.3
asdf global terraform 1.10.3

AWS CLI

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

gcloud

https://cloud.google.com/sdk/docs/install?hl=ja#deb

sudo apt update
sudo apt -y install apt-transport-https ca-certificates gnupg curl
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt update && sudo apt -y install google-cloud-cli
gtnaogtnao

Poetry

poetry new <snake_case_project_name>
poetry add <module>
poetry install
portry run python <main.py>