# 私のポータブル開発環境
開発環境自慢大会 2023.05.15
## コンセプト
- 30 min 以内に開発環境を復元できる
- 健康のために手ぶらで移動する
- セキュリティに気をつける
- 人生のすべてを Markdown で記述する
## 全体像
### マインドマップ
Web page
[My Portable Development Environment](https://atlas.mindmup.com/2023/05/4f22dfe0f2c811ed954967fe96427c01/my_portable_development_environment/index.html)
Thumbnail image

Embeded code
<iframe <iframe src="https://atlas.mindmup.com/2023/05/4f22dfe0f2c811ed954967fe96427c01/my_portable_development_environment/index.html"></iframe>
### 概要
- Mac と Chromebook がメイン
- 安いものを各所に置いておく
- ブラウザとリモートデスクトップを利用
- ローカル環境は一瞬で復元
## Mac mini (M1)
- 母艦
- Time Machine でバックアップを取る
- メモリもストレージも最小構成
- 8 万円くらい
- メモリ 8GB
- ユニファイドメモリと高速 SSD でストレスフル
- ストレージ
- macOS 標準でホームディレクトリの場所を変更できる 💡
- Samsung の外付け SSD へ
- [Samsung T7ポータブルSSD | サムスン半導体日本](https://semiconductor.samsung.com/jp/consumer-storage/portable-ssd/t7/)
- 極論、これを持ち運べば他人の Mac でも利用可能
### Chrome Tips
web ページをアプリ化できる 💡
- [Chrome アプリを追加して開く - Chrome ウェブストア ヘルプ](https://support.google.com/chrome_webstore/answer/3060053?hl=ja)
- 複数デバイスで同期できる
- Chromebook なら自動的に環境復元
![[chrome_shortcuts.png|200]]
## リモート環境
### Mac mini へ
- iPad から
- [Jump Desktop | Remote Desktop | iPad iPhone Android Mac Windows | Collaborative Screen Sharing](https://jumpdesktop.com/)
- Chromebook やブラウザから
- [Chrome Remote Desktop](https://remotedesktop.google.com/)
### Amazon WorkSpaces
- [Amazon WorkSpaces Client Download](https://clients.amazonworkspaces.com)
- Windows の動作確認
### クラウド IDE
- [Cloud IDE - AWS Cloud9 - AWS](https://aws.amazon.com/cloud9/)
- GitHub Codespaces に移行
- [GitHub Codespaces · GitHub](https://github.com/features/codespaces)
- 利用中
- [Developing with GitHub Codespaces](https://code.visualstudio.com/docs/remote/codespaces)
- その他 VS Code 系
- [The VS Code Server](https://code.visualstudio.com/blogs/2022/07/07/vscode-server)
- 今後の本命
- WebAssembly で Python を実行できたり
- [vscode.dev](https://vscode.dev)
- VS Code Server がホストされてる
- [GitHub - coder/code-server: VS Code in the browser](https://github.com/coder/code-server)
- OSS
- 自分で構築できる
- Chromebook で利用
- ![[Tech 🧠/Chromebook/images/1000.png|200]]
- [Remix - Ethereum IDE](https://remix.ethereum.org/)
- Smart Contract 開発
- [1on1 ミーティングのトピックを NFT にしました | イジゲングループ株式会社](https://www.wantedly.com/companies/ijgngroup/post_articles/500219)
## Samsung DeX
- [DeX|PC、TV、タブレットと無線接続 | Samsung Japan 公式](https://www.samsung.com/jp/apps/samsung-dex/)
- Galaxy 端末で利用可能
- 外部ディスプレイに繋ぐとデスクトップモードになる
- Mac や Windows 機も乗っ取れるようになった
### 利用例
Slack と Notion でお仕事中。
スマホ側は別でアプリを起動できる。
![[dex_setup_01.jpeg|200]]
![[dex_ss_01.jpg|200]]
GitHub Codespaces で AgentGPT を実行して画面を開く。
![[dex_setup_02.jpeg|200]]
![[dex_ss_02.jpg|200]]
Mac にリモートアクセスして Xcode を利用。
![[dex_ss_03.jpg|200]]
## 開発環境復元
### 流れ
1. マシンを調達する
1. 人のマシンの場合
1. ChromeOS Flex の boot USB メモリで Chromebook 化
2. Google アカウントの復元
1. Mac の Chrome or Chromebook 本体
2. 2FA
1. YubiKey を利用
1. [Yubico | YubiKey Strong Two Factor Authentication](https://www.yubico.com/)
3. ターミナル生活の復元
1. GitHub にアクセス
1. 2FA
1. YubiKey を利用
2. dotfiles のリポジトリを clone
1. private key
1. YubiKey を利用
3. Makefile であれこれ復元
1. 後述
YubiKey と boot USB メモリ
![[dex_ubikey_01.jpeg|200]]
## ターミナル生活
![[terminal_life.png|200]]
## 環境復元
### Makefile
**POINT** : Darwin (macOS) か? yum が使えるか?を判定しているので、同じコマンドで自動的にその環境にあったインストールが走る 💡
```sh
make basic
```
Makefile
```sh
UNAME := $(shell uname)
UPDATER = sudo yum update -y
INSTALLER = sudo yum install -y
ifeq ($(UNAME), Darwin)
UPDATER = brew update
INSTALLER = brew install
else
ifeq (, $(shell which yum))
UPDATER = sudo apt update && sudo apt upgrade -y
INSTALLER = sudo apt-get install -y
endif
endif
.PHONY: hello
hello:
@echo "Hello, world!"
@echo "INSTALLER: $(INSTALLER)"
ifeq ($(UNAME), Darwin)
.PHONY: basic
basic:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
$(INSTALLER) zsh tmux git
else
ifeq (, $(shell which chsh))
.PHONY: basic
basic:
$(INSTALLER) zsh tmux git
else
.PHONY: basic
basic:
$(INSTALLER) zsh tmux git util-linux-user
endif
endif
.PHONY: setup
setup: basic
git clone
[email protected]:hibi-myzk/dotfiles.git .dotfiles
rm -f ~/.gitconfig
ln -s ~/.dotfiles/.gitconfig ~/.gitconfig
rm -f ~/.tmux.conf
ln -s ~/.dotfiles/.tmux.conf ~/.tmux.conf
rm -f ~/.vim
ln -s ~/.dotfiles/.vim ~/.vim
rm -f ~/.vim-fuf-data
ln -s ~/.dotfiles/.vim-fuf-data ~/.vim-fuf-data
rm -f ~/.vimrc
ln -s ~/.dotfiles/.vimrc ~/.vimrc
rm -f ~/.zsh
ln -s ~/.dotfiles/.zsh ~/.zsh
rm -f ~/.zshenv
ln -s ~/.dotfiles/.zshenv ~/.zshenv
rm -f ~/.zsh-history
ln -s ~/.dotfiles/.zsh-history ~/.zsh-history
rm -f ~/.zshrc
ln -s ~/.dotfiles/.zshrc.zinit ~/.zshrc
rm -f ~/.p10k.zsh
ln -s ~/.dotfiles/.p10k.zsh .p10k.zsh
sudo chsh $(USER) -s $(shell which zsh)
vim -c ':PlugInstall' -c ':qa'
.PHONY: mac
mac: setup
rm -f ~/.zprofile
ln -s ~/.dotfiles/.zprofile.mac .zprofile
.PHONY: docker
docker:
$(INSTALLER) docker
sudo service docker start
#sudo groupadd docker
sudo usermod -aG docker $(USER)
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(shell uname -s)-$(shell uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
@echo "Log out and log back in."
.PHONY: obsidian
obsidian:
git clone
[email protected]:hibi-myzk/obsidian-vault.git obsidian
.PHONY: autossh
autossh:
$(INSTALLER) autossh
.PHONY: ssh-port-forwarding
ssh-port-forwarding:
autossh -f -N -M 0 -R 8887:localhost:22 tofu
```
### Homeblue Tips
`requirements.txt` みたいなことができる 💡
```sh
## output
brew leaves > my_formula.txt
## install
xargs brew install < my_formula.txt
```
```sh
## output
brew rew list --cask -1 > my_cask_formula.txt
## install
xargs brew cask install < my_cask_formula.txt
```
### ssh
- [Blink Shell is a professional, desktop grade terminal for iOS. With Mosh & SSH clients for iOS, lightning fast and fully customizable. The best terminal for iOS and iPadOS.](https://blink.sh/)
- iPad のおすすめアプリ
- ssh port forwarding
- `autossh -f -N -M 0 -R 8887:localhost:22 host`
- 用途
- リモートサーバー経由で自宅の端末 (Raspberry Pi) などにアクセス
- Mac で xcodebuild を使って iOS アプリのビルドをできるようにしておく
### Zsh
- Z
- [GitHub - rupa/z: z - jump around](https://github.com/rupa/z)
- Zinit
- [GitHub - zdharma-continuum/zinit: 🌻 Flexible and fast ZSH plugin manager](https://github.com/zdharma-continuum/zinit)
#### Hibi's .zshrc
.zshrc
```sh
#export LANG=ja_JP.UTF-8
export LANG=en_US.UTF-8
export LESSCHARSET=utf-8
HISTFILE=$HOME/.dotfiles/.zsh-history
HISTSIZE=100000
SAVEHIST=100000
## 補完機能の強化
autoload -U compinit
compinit
## コアダンプサイズを制限
limit coredumpsize 102400
## 出力の文字列末尾に改行コードが無い場合でも表示
unsetopt promptcr
## 色を使う
setopt prompt_subst
## zsh-git
# https://github.com/jcorbin/zsh-git
# Load the prompt theme system
autoload -U promptinit
promptinit
# zsh-git
# Use the wunjo prompt theme
prompt wunjo
## prompt
PROMPT+="%2/%% "
## ビープを鳴らさない
setopt nobeep
## 内部コマンド jobs の出力をデフォルトで jobs -l にする
setopt long_list_jobs
## 補完候補一覧でファイルの種別をマーク表示
setopt list_types
## サスペンド中のプロセスと同じコマンド名を実行した場合はリジューム
setopt auto_resume
## 補完候補を一覧表示
setopt auto_list
## 直前と同じコマンドをヒストリに追加しない
setopt hist_ignore_dups
## cd 時に自動で push
setopt autopushd
## 同じディレクトリを pushd しない
setopt pushd_ignore_dups
## ファイル名で #, ~, ^ の 3 文字を正規表現として扱う
#setopt extended_glob
## TAB で順に補完候補を切り替える
setopt auto_menu
## zsh の開始, 終了時刻をヒストリファイルに書き込む
setopt extended_history
## =command を command のパス名に展開する
setopt equals
## --prefix=/usr などの = 以降も補完
setopt magic_equal_subst
## ヒストリを呼び出してから実行する間に一旦編集
setopt hist_verify
# ファイル名の展開で辞書順ではなく数値的にソート
setopt numeric_glob_sort
## 出力時8ビットを通す
setopt print_eight_bit
## ヒストリを共有
setopt share_history
## 補完候補のカーソル選択を有効に
zstyle ':completion:*:default' menu select=1
## 補完候補の色づけ
zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
## ディレクトリ名だけで cd
setopt auto_cd
## カッコの対応などを自動的に補完
setopt auto_param_keys
## ディレクトリ名の補完で末尾の / を自動的に付加し、次の補完に備える
setopt auto_param_slash
## スペルチェック
setopt correct
## Timezone
export TZ=/usr/share/zoneinfo/Asia/Tokyo
## Z
. ~/.dotfiles/z.sh
## npm
export PATH=/usr/local/share/npm/bin:$PATH
## Alias
alias ls='ls -G'
alias lsl='ls -l'
alias lsal='ls -al'
alias lsa='ls -a'
alias lvim="vim -c \"normal '0\""
alias rgrep='find . -name "*.svn*" -prune -o -type f -print0 | xargs -0 grep'
alias rserver="ruby -r webrick -e \"WEBrick::HTTPServer.new(Port: (ARGV[1] || 8000).to_i, DocumentRoot: File.join(Dir::pwd, ARGV[0] || 'html')).tap {|s| trap('INT') { s.shutdown } }.start\""
alias firter="ruby -e \"STDIN.readlines.map(&:chomp).tap{|lines|puts eval(ARGV.shift || '')}\""
## Rails
alias r='rails'
alias spec='spec -c -fs'
alias rc='pry -r ./config/environment'
## Vim
alias vims='vim -S'
## Git
alias g='git'
alias gs='git status'
alias gb='git branch'
alias gco='git commit'
alias gf='git fetch'
## Subversion
alias vs='svn status'
alias scm='svn commit -m'
## Memo
#
# Reload DNS
# % dscacheutil -flushcache
# since Lion
# % sudo killall -HUP mDNSResponder
```
.zshrc.zinit
```sh
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
### Added by Zinit's installer
if [[ ! -f $HOME/.zinit/bin/zinit.zsh ]]; then
print -P "%F{33}▓▒░ %F{220}Installing %F{33}DHARMA%F{220} Initiative Plugin Manager (%F{33}zdharma/zinit%F{220})…%f"
command mkdir -p "$HOME/.zinit" && command chmod g-rwX "$HOME/.zinit"
command git clone https://github.com/zdharma/zinit "$HOME/.zinit/bin" && \
print -P "%F{33}▓▒░ %F{34}Installation successful.%f%b" || \
print -P "%F{160}▓▒░ The clone has failed.%f%b"
fi
source "$HOME/.zinit/bin/zinit.zsh"
autoload -Uz _zinit
(( ${+_comps} )) && _comps[zinit]=_zinit
### End of Zinit's installer chunk
# Theme
zinit ice depth=1; zinit light romkatv/powerlevel10k
# Auto complition
zinit light zsh-users/zsh-autosuggestions
# Syntax highlighting
zinit light zdharma/fast-syntax-highlighting
# Ctrl+r : search history
zinit light zdharma/history-search-multi-word
# `git open` to open GitHub on your browser
zinit light paulirish/git-open
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
# Language
#export LANG=ja_JP.UTF-8
export LANG=en_US.UTF-8
export LESSCHARSET=utf-8
# History
HISTFILE=${HOME}/.dotfiles/.zsh-history
HISTSIZE=100000
SAVEHIST=100000
setopt hist_verify
setopt share_history
setopt extended_history
# No beep
setopt nobeep
# Timezone
export TZ=/usr/share/zoneinfo/Asia/Tokyo
# Z
. ~/.dotfiles/z.sh
# Utility
alias rgrep='find . -name "*.svn*" -prune -o -type f -print0 | xargs -0 grep'
alias wttr='curl wttr.in/Fukuoka'
```
`.zprofile` は ``.zprofile.mac` など作って Mac と Linux で分けている。
### Vim
![[vim_life.png|200]]
#### Hibi's .vimrc
.vimrc
```sh
" curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
" :PlugInstall
" :GoInstallBinaries
" toggle comment
" `gcc`
" plugins
call plug#begin()
Plug 'itchyny/lightline.vim'
Plug 'itchyny/vim-gitbranch'
Plug 'lambdalisue/fern.vim'
" :Fern-drawer .
" select -> [-] -> shift + C -> shift + P
Plug 'mbbill/undotree'
Plug 'thinca/vim-quickrun'
" :QuickRun
Plug 'Shougo/context_filetype.vim'
Plug 'tyru/caw.vim'
" visual -> gcc
Plug 't9md/vim-quickhl'
" visual -> shift + H
Plug 'mattn/vim-lexiv'
Plug 'mattn/vim-sonictemplate'
" Template Completion
" :Template <tab>
" :Template readme-sharp
" Postfix Completion
" control + Y -> control + B
Plug 'ctrlpvim/ctrlp.vim'
" control + P
Plug 'previm/previm'
Plug 'tyru/open-browser.vim'
" :PrevimOpen
Plug 'skanehira/preview-markdown.vim'
" :PreviewMarkdown
Plug 'fatih/vim-go'
" :help vim-go
call plug#end()
" status bar
set laststatus=2
set noshowmode
let g:lightline = {
\ 'colorscheme': 'one',
\ 'active': {
\ 'left': [ [ 'mode', 'paste' ],
\ [ 'gitbranch', 'readonly', 'filename', 'modified' ] ]
\ },
\ 'component_function': {
\ 'gitbranch': 'gitbranch#name'
\ },
\ }
" encoding
set encoding=utf-8
set fileencodings=utf-8,iso-2022-jp,euc-jp,ucs-2le,ucs-2,cp932
" file type
filetype indent on
" disable beep sound
set vb t_vb=
" show number
set number
" yank and paste between files
map <silent> sy :call YanktmpYank()<CR>
map <silent> sp :call YanktmpPaste_p()<CR>
map <silent> sP :call YanktmpPaste_P()<CR>
" open last line
:au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("