Oracle Cloud で立ち上げる Windows compute インスタンスの初期設定を cloudbase-initで自動化する


Windows server をクラウドで立ち上げた時には、いろいろ初期化作業があり、Oracle cloud も例外ではありませんが、ここでは cloudbase-init を使って初期設定を可能な限り自動化して Compute インスタンスを立ち上げてみたいと思います。

初期化時にやりたい作業は・・・

- パスワードの再設定
- Locale の日本化
- Keyboard の日本語対応
- Timezone の東京化
- Password の無期限化
- 定番アプリのインストール
- Security patch の適応

等です、これらを自動処理するスクリプトを下記用意します。
ところで、ここで、cloud-initと cloudbase-init との違いですが、Windowsが対象の場合はcloudbase-initと呼ぶと、識別していただけば良いと思います。
## 手順


### 1: Compute Instance の起動画面て cloudbase-initのセット
Windows server のインスタンス立ち上げ画面で・・・

拡張オプションの表示、をクリックします。
すると cloud-initと表記されたcloudbase-init の記述欄が下にあるので、以下にある powershell スクリプトを貼り付けます、再初期化パスワードは 「新しいパスワード」の記述を置換してください。
cloudbase-init は Powershell を必須とはしていませんが、今回は Powershell で記述します。
![rapture_20200526112010.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/9f6b0b80-1297-59a8-0b90-e22c5649c3f9.jpeg)

### 2: Windows server Compute Instance を立ち上げます。
普通に「作成」を押してインスタンスを立ち上げます

### 3: 再起動
Compute Instance が立ち上がって、左側の[I]のアイコンが緑色になったら、[再起動]をクリックして OS をコンソールから再起動させます、ここが今回のミソです。
![rapture_20200526112025.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/38f0393a-88e5-5629-6eb3-9c4ead3b10cc.jpeg)


再起動が完了してまたアイコンが緑色になったら、Remote Desktop から login してみましょう、
なお、login 直後は、まだバックグラウンドで cloudbase-init アカウントによって、install 作業が続いているので Desktop 上に順番にアプリケーションのアイコンが出現してくるのが見えます。
インストール完了時のデスクトップがこちら、IMEがinstallされて Timezoneも日本に合っています、仕上がってますね、Windows server立ち上げ時の標準スクリプトにいかがでしょうか。
![rapture_20200526112037.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/0489e2f0-c212-d08e-eb23-97d8383d1904.jpeg)


使用するPowershell スクリプト

```powershell:cloud-init.ps1
<powershell>
net user opc "新しいパスワード"
$WantFile = "$env:userprofile\pass1.txt"

if (!(Test-Path $WantFile)) {
#pass1
	Write-Host "first boot!"
	New-Item -Path $env:userprofile -Name "pass1.txt" -ItemType "file" -Value "second file."

	$LpUrl = "http://download.windowsupdate.com/c/msdownload/update/software/updt/2016/09/"
	$LpFile = "lp_9a666295ebc1052c4c5ffbfa18368dfddebcd69a.cab"
	$LpTemp = "C:\LpTemp.cab"
	Set-WinUserLanguageList -LanguageList ja-JP,en-US -Force
	Start-BitsTransfer -Source $LpUrl$LpFile -Destination $LpTemp -Priority High
	Add-WindowsPackage -PackagePath $LpTemp -Online
	Set-WinDefaultInputMethodOverride -InputTip "0411:00000411"
	Set-WinLanguageBarOption -UseLegacySwitchMode -UseLegacyLanguageBar
	Remove-Item $LpTemp -Force

	# Chocolatey install
	Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

	Set-WinUILanguageOverride -Language ja-JP
	Set-WinCultureFromLanguageListOptOut -OptOut $False
	Set-WinHomeLocation -GeoId 0x7A
	Set-WinSystemLocale -SystemLocale ja-JP
	Set-TimeZone -Id "Tokyo Standard Time"
	# exit 1003 means error exit
	exit 1003

} else {
#pass2
	Write-Host "Second boot"
	New-Item -Path $env:userprofile -Name "pass2.txt" -ItemType "file" -Value "First file."
	Set-WinUILanguageOverride ja-JP
	wmic useraccount where "Name=opc" set PasswordExpires=FALSE

	$ci = New-CimInstance -Namespace root/Microsoft/Windows/WindowsUpdate -ClassName MSFT_WUOperationsSession
	$result = $ci | Invoke-CimMethod -MethodName ScanForUpdates -Arguments @{SearchCriteria="IsInstalled=0";OnlineScan=$true}
	$result.Updates
	Invoke-CimMethod -InputObject $ci -MethodName ApplyApplicableUpdates

	choco install googlechrome -y
	choco install dotnet4.5 -y
	choco install dotnet4.7 -y
	choco install firefox -y
	choco install jq -y
	choco install openssh -y
	choco install teraterm -y
	choco install git -y
	choco install python3 -y
	choco install winscp -y
	choco install curl -y
	choco install graalvm-java11 -y
	choco install cyberduck -y
	choco install ripgrep-all -y
	choco install less -y
	choco install sed -y
	choco install dos2unix -y
	choco install unzip -y
	choco install peco -y
	choco install nodejs -y
	choco install advanced-ip-scanner -y
	choco install logrotate -y
	choco install iperf3 -y
	choco install vscode -y
	choco install which -y
	choco install wget -y
	refreshenv
}
</powershell>
```

# Tips:

## exit 1003 とは

exit 1003 とは cloudbase-init を error 終了するので、再起動した場合も再び cloudbase-init を動かします、
という意味です。なので、コンソールから再起動しても再び cloud-init のスクリプトが動作する訳ですが、そのまま再起動しても無限ループになるだけなので、動作の過程をファイルに保存し、再起動時には次のステップから動作させるようにしています。
今回は 2 段階実行ですが、3 段階に拡張する事も、この方法でできます。
cloudbaseの仕様について、下記リンクに記載があります。
https://cloudbase-init.readthedocs.io/en/latest/tutorial.html?highlight=1003#file-execution

## File の存在で分岐させる Powershell の書き方

https://stackoverflow.com/questions/43479451/powershell-does-file-exist-on-users-machine-output-specific-file

## 初期 install できないタイプのアプリ

この一連のインストール処理は、cloudbase-init という、init 起動時のみ使われるアカウントにおいて、実施されます。
従って c:\Users\cloudbase-init 以下にインストールされるタイプのアプリケーション、例えば sourcetree などのインストールはここで実施しても標準の opc のアカウントからは見えないので意味がありません、opc で login してからインストールしましょう。
Windows の package manager の Chocolatey は既に有効化してあります。
ユーザー毎にインストールされるアプリケーションは、例えばこんなコマンドを opc で login してから、Powershell の管理者権限で実行します。

```powershell:Install-Application.ps1
choco install sourcetree -y
choco install oracle-sql-developer -y --params "'/Username:xxx@yyy.com /Password:xxxx'"
# Oracleのアカウントは作ってあること
```

## Windows server インスタンスの立て方

ここでは、Windows server インスタンスの立て方自体は詳しくは説明していません。詳しくは、このあたりを参考にしてみてください。
https://blogs.techvan.co.jp/oci/2018/09/05/oracle-cloud-infrastructure%E3%81%A7windows%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E5%BB%BA%E3%81%A6%E3%81%A6%E3%81%BF%E3%81%9F/