22 Jan 2018, 22:00

Azureのリソースグループ限定 共同作成者をいい感じに作る

共同作成者は、ちょっと強い

Azureのリソースグループは、リソースを任意のグループにまとめ、ライフサイクルや権限の管理を一括して行える便利なコンセプトです。

ユースケースのひとつに、”本番とは分離した開発向けリソースグループを作って、アプリ/インフラ開発者に開放したい”、があります。新しい技術は試行錯誤で身につくので、こういった環境は重要です。

なのですが、このようなケースで、権限付与の落とし穴があります。

  • サブスクリプション所有者が開発用リソースグループを作る
  • スコープを開発用リソースグループに限定し、開発者に対し共同作成者ロールを割り当てる
  • 開発者はリソースグループ限定で、のびのび試行錯誤できて幸せ
  • 開発者がスッキリしたくなり、リソースグループごとバッサリ削除 (共同作成者なので可能)
  • 開発者にはサブスクリプションレベルの権限がないため、リソースグループを作成できない
  • 詰む
  • サブスクリプション所有者が、リソースグループ作成と権限付与をやり直し

共同作成者ロールから、リソースグループの削除権限だけを除外できると、いいんですが。そこでカスタムロールの出番です。リソースグループ限定、グループ削除権限なしの共同作成者を作ってみましょう。

いい感じのカスタムロールを作る

Azureのカスタムロールは、個別リソースレベルで粒度の細かい権限設定ができます。ですが、やり過ぎると破綻するため、シンプルなロールを最小限作る、がおすすめです。

シンプルに行きましょう。まずはカスタムロールの定義を作ります。role.jsonとします。

{
    "Name": "Resource Group Contributor",
    "IsCustom": true,
    "Description": "Lets you manage everything except access to resources, but can not delete Resouce Group",
    "Actions": [
        "*"
    ],
    "NotActions": [
        "Microsoft.Authorization/*/Delete",
        "Microsoft.Authorization/*/Write",
        "Microsoft.Authorization/elevateAccess/Action",
        "Microsoft.Resources/subscriptions/resourceGroups/Delete"
    ],
    "AssignableScopes": [
        "/subscriptions/your-subscriotion-id"
    ]
}

組み込みロールの共同作成者をテンプレに、NotActionsでリソースグループの削除権限を除外しました。AssignableScopesでリソースグループを限定してもいいですが、リソースグループの数だけロールを作るのはつらいので、ここでは指定しません。後からロールを割り当てる時にスコープを指定します。

では、カスタムロールを作成します。

$ az role definition create --role-definition ./role.json

出力にカスタムロールのIDが入っていますので、控えておきます。

"id": "/subscriptions/your-subscriotion-id/providers/Microsoft.Authorization/roleDefinitions/your-customrole-id"

カスタムロールをユーザー、グループ、サービスプリンシパルに割り当てる

次に、ユーザー/グループに先ほど作ったカスタムロールを割り当てます。スコープはリソースグループに限定します。

$ az role assignment create --assignee-object-id your-user-or-group-object-id --role your-customrole-id --scope "/subscriptions/your-subscriotion-id/resourceGroups/sample-dev-rg"

サービスプリンシパル作成時に割り当てる場合は、以下のように。

$ az ad sp create-for-rbac -n "rgcontributor" -p "your-password" --role your-customrole-id --scopes "/subscriptions/your-subscriotion-id/resourceGroups/sample-dev-rg"

余談ですが、”az ad sp create-for-rbac”コマンドはAzure ADアプリケーションを同時に作るため、別途アプリを作ってサービスプリンシパルと紐づける、という作業が要りません。

試してみる

ログインして試してみましょう。サービスプリンシパルの例です。

$ az login --service-principal -u "http://rgcontributor" -p "your-password" -t "your-tenant-id"

検証したサブスクリプションには多数のリソースグループがあるのですが、スコープで指定したものだけが見えます。

$ az group list -o table
Name              Location    Status
----------------  ----------  ---------
sample-dev-rg  japaneast   Succeeded

このリソースグループに、VMを作っておきました。リストはしませんが、ストレージやネットワークなど関連リソースもこのグループにあります。

$ az vm list -o table
Name              ResourceGroup     Location
----------------  ----------------  ----------
sampledevvm01     sample-dev-rg  japaneast

試しにリソースグループを作ってみます。サブスクリプションスコープの権限がないため怒られます。

$ az group create -n rgc-poc-rg -l japaneast
The client 'aaaaa-bbbbb-ccccc-ddddd-eeeee' with object id 'aaaaa-bbbbb-ccccc-ddddd-eeeee' does not have authorization to perform action 'Microsoft.Resources/subscriptions/resourcegroups/write' over scope '/subscriptions/your-subscriotion-id/resourcegroups/rgc-poc-rg'.

リソースグループを消してみます。消すかい? -> y -> ダメ、という、持ち上げて落とす怒り方です。

$ az group delete -n sample-dev-rg
Are you sure you want to perform this operation? (y/n): y
The client 'aaaaa-bbbbb-ccccc-ddddd-eeeee' with object id 'aaaaa-bbbbb-ccccc-ddddd-eeeee' does not have authorization to perform action 'Microsoft.Resources/subscriptions/resourcegroups/delete' over scope '/subscriptions/your-subscriotion-id/resourcegroups/sample-dev-rg'.

でもリソースグループのリソースを一括削除したい

でも、リソースグループは消せなくても、リソースをバッサリ消す手段は欲しいですよね。そんな時には空のリソースマネージャーテンプレートを、completeモードでデプロイすると、消せます。

空テンプレートを、empty.jsonとしましょう。

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "variables": {},
    "resources": [],
    "outputs": {}
}

破壊的空砲を打ちます。

$ az group deployment create --mode complete -g sample-dev-rg --template-file ./empty.json

リソースグループは残ります。

$ az group list -o table
Name              Location    Status
----------------  ----------  ---------
sample-dev-rg  japaneast   Succeeded

VMは消えました。リストしませんが、他の関連リソースもバッサリ消えています。

$ az vm list -o table

08 Jan 2018, 16:30

TerraformでAzure サンプル 2018/1版

サンプルのアップデート

年末にリポジトリの大掃除をしていて、2年前に書いたTerraform & Azureの記事に目が止まりました。原則はいいとして、サンプルは2年物で腐りかけです。ということでアップデートします。

インパクトの大きな変更点

Terraformの、ここ2年の重要なアップデートは以下でしょうか。Azure視点で。

  1. BackendにAzure Blobを使えるようになった
  2. Workspaceで同一コード・複数環境管理ができるようになった
  3. 対応リソースが増えた
  4. Terraform Module Registryが公開された

更新版サンプルの方針

重要アップデートをふまえ、以下の方針で新サンプルを作りました。

チーム、複数端末での運用

BackendにAzure Blobがサポートされたので、チーム、複数端末でstateの共有がしやすくなりました。ひとつのプロジェクトや環境を、チームメンバーがどこからでも、だけでなく、複数プロジェクトでのstate共有もできます。

Workspaceの導入

従来は /dev /stage /prodなど、環境別にコードを分けて管理していました。ゆえに環境間のコード同期が課題でしたが、TerraformのWorkspace機能で解決しやすくなりました。リソース定義で ${terraform.workspace} 変数を参照するように書けば、ひとつのコードで複数環境を扱えます。

要件によっては、従来通り環境別にコードを分けた方がいいこともあるでしょう。環境間の差分が大きい、開発とデプロイのタイミングやライフサイクルが異なるなど、Workspaceが使いづらいケースもあるでしょう。その場合は無理せず従来のやり方で。今回のサンプルは「Workspaceを使ったら何ができるか?」を考えるネタにしてください。

Module、Terraform Module Registryの活用

TerraformのModuleはとても強力な機能なのですが、あーでもないこーでもないと、こだわり過ぎるとキリがありません。「うまいやり方」を見てから使いたいのが人情です。そこでTerraform Module Registryを活かします。お墨付きのVerifiedモジュールが公開されていますので、そのまま使うもよし、ライセンスを確認の上フォークするのもよし、です。

リソースグループは環境ごとに準備し、管理をTerraformから分離

AzureのリソースをプロビジョニングするTerraformコードの多くは、Azureのリソースグループを管理下に入れている印象です。すなわちdestroyするとリソースグループごとバッサリ消える。わかりやすいけど破壊的。

TerraformはApp ServiceやACIなどPaaS、アプリ寄りのリソースも作成できるようになってきたので、アプリ開発者にTerraformを開放したいケースが増えてきています。dev環境をアプリ開発者とインフラ技術者がコラボして育て、そのコードをstageやprodにデプロイする、など。

ところで。TerraformのWorkspaceは、こんな感じで簡単に切り替えられます。

terraform workspace select prod

みなまで言わなくても分かりますね。悲劇はプラットフォーム側で回避しましょう。今回のサンプルではリソースグループをTerraform管理下に置かず、別途作成します。Terraformからはdata resourcesとしてRead Onlyで参照する実装です。環境別のリソースグループを作成し、dev環境のみアプリ開発者へ権限を付与します。

サンプル解説

サンプルはGitHubに置きました。合わせてご確認ください。

このコードをapplyすると、以下のリソースが出来上がります。

  • NGINX on Ubuntu Webサーバー VMスケールセット
  • VMスケールセット向けロードバランサー
  • 踏み台サーバー
  • 上記を配置するネットワーク (仮想ネットワーク、サブネット、NSG)

リポジトリ構造

サンプルのリポジトリ構造です。

├── modules
│   ├── computegroup
│   │   ├── main.tf
│   │   ├── os
│   │   │   ├── outputs.tf
│   │   │   └── variables.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   ├── loadbalancer
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   └── network
│       ├── main.tf
│       ├── outputs.tf
│       └── variables.tf
└── projects
    ├── project_a
    │   ├── backend.tf
    │   ├── main.tf
    │   ├── outputs.tf
    │   └── variables.tf
    └── shared
        ├── backend.tf
        ├── main.tf
        ├── outputs.tf
        └── variables.tf

/modulesにはTerraform Module RegistryでVerifiedされているモジュールをフォークしたコードを入れました。フォークした理由は、リソースグループをdata resource化して参照のみにしたかったためです。

そして、/projectsに2つのプロジェクトを作りました。プロジェクトでリソースとTerraformの実行単位、stateを分割します。sharedで土台となる仮想ネットワークと踏み台サーバー関連リソース、project_aでVMスケールセットとロードバランサーを管理します。

このボリュームだとプロジェクトを分割する必然性は低いのですが、以下のケースにも対応できるように分けました。

  • アプリ開発者がproject_a下でアプリ関連リソースに集中したい
  • 性能観点で分割したい (Terraformはリソース量につれて重くなりがち)
  • 有事を考慮し影響範囲を分割したい

プロジェクト間では、stateをremote_stateを使って共有します。サンプルではsharedで作成した仮想ネットワークのサブネットIDをoutputし、project_aで参照できるよう定義しています。

使い方

前提

  • Linux、WSL、macOSなどbash環境の実行例です
  • SSHの公開鍵をTerraform実行環境の ~/.ssh/id_rsa.pub として準備してください

管理者向けのサービスプリンシパルを用意する

インフラのプロビジョニングの主体者、管理者向けのサービスプリンシパルを用意します。リソースグループを作成できる権限が必要です。

もしなければ作成します。組み込みロールでは、サブスクリプションに対するContributorが妥当でしょう。Terraformのドキュメントも参考に。

az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/SUBSCRIPTION_ID"

出力されるappId、password、tenantを控えます。既存のサービスプリンシパルを使うのであれば、同情報を確認してください。

なお参考までに。Azure Cloud ShellなどAzure CLIが導入されている環境では、特に認証情報の指定なしでterraform planやapply時にAzureのリソースにアクセスできます。TerraformがCLIの認証トークンを使うからです。

そしてBackendをAzure Blobとする場合、Blobにアクセスするためのキーが別途必要です。ですが、残念ながらBackendロジックでキーを得る際に、このトークンが使われません。キーを明示することもできますが、Blobのアクセスキーは漏洩時のリカバリーが大変です。できれば直に扱いたくありません。

サービスプリンシパル認証であれば、Azureリソースへのプロビジョニング、Backendアクセスどちらも対応できます。これがこのサンプルでサービスプリンシパル認証を選んだ理由です。

管理者の環境変数を設定する

Terraformが認証関連で必要な情報を環境変数で設定します。先ほど控えた情報を使います。

export ARM_SUBSCRIPTION_ID="<your subscription id>"
export ARM_CLIENT_ID="<your servicce principal appid>"
export ARM_CLIENT_SECRET="<your service principal password>"
export ARM_TENANT_ID="<your service principal tenant>"

Workspaceを作る

開発(dev)/ステージング(stage)/本番(prod)、3つのWorkspaceを作る例です。

terraform workspace new dev
terraform workspace new stage
terraform workspace new prod

リソースグループを作る

まずWorkspace別にリソースグループを作ります。

az group create -n tf-sample-dev-rg -l japaneast
az group create -n tf-sample-stage-rg -l japaneast
az group create -n tf-sample-prod-rg -l japaneast

リソースグループ名にはルールがあります。Workspace別にリソースグループを分離するため、Terraformのコードで ${terraform.workspace} 変数を使っているためです。この変数は実行時に評価されます。

data "azurerm_resource_group" "resource_group" {
  name = "${var.resource_group_name}-${terraform.workspace}-rg"
}

${var.resource_group_name} は接頭辞です。サンプルではvariables.tfで”tf-sample”と指定しています。

次にBackend、state共有向けリソースグループを作ります。

az group create -n tf-sample-state-rg -l japaneast

このリソースグループは、各projectのbackend.tfで指定しています。

terraform {
  backend "azurerm" {
    resource_group_name  = "tf-sample-state-rg"
    storage_account_name = "<your storage account name>"
    container_name       = "tfstate-project-a"
    key                  = "terraform.tfstate"
  }
}

最後にアプリ開発者がリソースグループtf-sample-dev-rg、tf-sample-state-rgへアクセスできるよう、アプリ開発者向けサービスプリンシパルを作成します。

az ad sp create-for-rbac --role="Contributor" --scopes "/subscriptions/<your subscription id>/resourceGroups/tf-sample-dev-rg" "/subscriptions/<your subscription id>/resourceGroups/tf-sample-state-rg"

出力されるappId、password、tenantは、アプリ開発者向けに控えておきます。

Backendを準備する

project別にストレージアカウントとコンテナーを作ります。tf-sample-state-rgに

  • ストレージアカウント (名前は任意)
  • コンテナー *2 (tfstate-project-a, tfstate-shared)

を作ってください。GUIでもCLIでも、お好きなやり方で。

その後、project_a/backend.tf.sample、shared/backend.tf.sampleをそれぞれbackend.tfにリネームし、先ほど作ったストレージアカウント名を指定します。以下はproject_a/backend.tf.sampleの例。

terraform {
  backend "azurerm" {
    resource_group_name  = "tf-sample-state-rg"
    storage_account_name = "<your storage account name>"
    container_name       = "tfstate-project-a"
    key                  = "terraform.tfstate"
  }
}

data "terraform_remote_state" "shared" {
  backend = "azurerm"

  config {
    resource_group_name  = "tf-sample-state-rg"
    storage_account_name = "<your storage account name>"
    container_name       = "tfstate-shared"
    key                  = "terraform.tfstateenv:${terraform.workspace}"
  }
}

これで準備完了です。

実行

Workspaceをdevに切り替えます。

terraform workspace select dev

まずは土台となるリソースを作成するsharedから。

cd shared
terraform init
terraform plan
terraform apply

土台となるリソースが作成されたら、次はproject_aを。

cd ../project_a
terraform init
terraform plan
terraform apply

ここでは割愛しますが、dev向けサービスプリンシパルで認証しても、dev Workspaceではplan、apply可能です。

dev Workspaceでコードが育ったら、stage/prod Workspaceに切り替えて実行します。

terraform workspace select stage
[以下devと同様の操作]

当然、dev向けサービスプリンシパルで認証している場合は、stage/prodでのplan、apply、もちろんdestroyも失敗します。stage/prod リソースグループにアクセスする権限がないからです。

参考情報

04 Dec 2017, 22:00

Windows上でLinux向けGoバイナリをDockerでビルドする

小ネタです

Goはクロスプラットフォーム開発しやすい言語なのですが、Windows上でLinux向けバイナリーをビルドするなら、gccが要ります。正直なところ入れたくありません。なのでDockerでやります。

条件

  • Docker for Windows
    • Linuxモード
    • ドライブ共有

PowerShell窓で実行

ビルドしたいGoのソースがあるディレクトリで以下のコマンドを実行します。Linux向けバイナリーが同じディレクトリに出来ます。

docker run --rm -it -e GOPATH=/go --mount type=bind,source=${env:GOPATH},target=/go --mount type=bind,source=${PWD},target=/work -w /work golang:1.9.2-alpine go build -a -tags netgo -installsuffix netgo -o yourapp_linux
  • golang:1.9.2-alpine DockerイメージはGOPATHに/goを設定してビルドされていますが、念のため実行時にも設定
  • -v オプションでのマウントは非推奨になったので –mount で
  • スタティックリンク

28 Nov 2017, 08:45

Azure Blob アップローダーをGoで書いた、そしてその理由

Azure Blob アップローダーをGoで書いた

ふたつほど理由があり、GolangでAzure Blobのファイルアップローダーを書きました。

ひとつめの理由: SDKが新しくなったから

最近公式ブログで紹介された通り、Azure Storage SDK for Goが再設計され、プレビューが始まりました。GoはDockerやKubernetes、Terraformなど最近話題のプラットフォームやツールを書くのに使われており、ユーザーも増えています。再設計してもっと使いやすくしてちょ、という要望が多かったのも、うなずけます。

ということで、新しいSDKで書いてみたかった、というのがひとつめの理由です。ローカルにあるファイルを読んでBlobにアップロードするコードは、こんな感じ。

(2018/6/17) 更新

  • SDKバージョンを 2017-07-29 へ変更
  • 関数 UploadStreamToBlockBlob を UploadFileToBlockBlob に変更
  • Parallelism オプションを追加
  • ヘルパー関数 handleErrors を追加
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net/url"
	"os"

	"github.com/Azure/azure-storage-blob-go/2017-07-29/azblob"
)

var (
	accountName    string
	accountKey     string
	containerName  string
	fileName       string
	blockSize      int64
	blockSizeBytes int64
	parallelism    int64
)

func init() {
	flag.StringVar(&accountName, "account-name", "", "(Required) Storage Account Name")
	flag.StringVar(&accountKey, "account-key", "", "(Required) Storage Account Key")
	flag.StringVar(&containerName, "c", "", "(Required - short option) Blob Container Name")
	flag.StringVar(&containerName, "container-name", "", "(Required) Blob Container Name")
	flag.StringVar(&fileName, "f", "", "(Required - short option) Upload filename")
	flag.StringVar(&fileName, "file", "", "(Required) Upload filename")
	flag.Int64Var(&blockSize, "b", 4, "(Optional - short option) Blob Blocksize (MB) - From 1 to 100. Max filesize depends on this value. Max filesize = Blocksize * 50,000 blocks")
	flag.Int64Var(&blockSize, "blocksize", 4, "(Optional) Blob Blocksize (MB) - From 1 to 100. Max filesize depends on this value. Max filesize = Blocksize * 50,000 blocks")
	flag.Int64Var(&parallelism, "p", 5, "(Optional - short option) Parallelism - From 0 to 32. Default 5.")
	flag.Int64Var(&parallelism, "parallelism", 5, "(Optional) Parallelism - From 0 to 32. Default 5.")
	flag.Parse()

	if (blockSize < 1) || (blockSize > 100) {
		fmt.Println("Blocksize must be from 1MB to 100MB")
		os.Exit(1)
	}
	blockSizeBytes = blockSize * 1024 * 1024

	if (parallelism < 0) || (parallelism > 32) {
		fmt.Println("Parallelism must be from 0 to 32")
		os.Exit(1)
	}
}

func handleErrors(err error) {
	if err != nil {
		if serr, ok := err.(azblob.StorageError); ok { // This error is a Service-specific
			switch serr.ServiceCode() { // Compare serviceCode to ServiceCodeXxx constants
			case azblob.ServiceCodeContainerAlreadyExists:
				fmt.Println("Received 409. Container already exists")
				return
			}
		}
		log.Fatal(err)
	}
}

func main() {
	file, err := os.Open(fileName)
	handleErrors(err)
	defer file.Close()

	fileSize, err := file.Stat()
	handleErrors(err)

	u, _ := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", accountName, containerName, fileName))
	blockBlobURL := azblob.NewBlockBlobURL(*u, azblob.NewPipeline(azblob.NewSharedKeyCredential(accountName, accountKey), azblob.PipelineOptions{}))

	ctx := context.Background()

	fmt.Println("Uploading block blob...")
	response, err := azblob.UploadFileToBlockBlob(ctx, file, blockBlobURL,
		azblob.UploadToBlockBlobOptions{
			BlockSize: blockSizeBytes,
			Progress: func(bytesTransferred int64) {
				fmt.Printf("Uploaded %d of %d bytes.\n", bytesTransferred, fileSize.Size())
			},
			Parallelism: uint16(parallelism),
		})
	handleErrors(err)
	_ = response // Avoid compiler's "declared and not used" error

	fmt.Println("Done")
}

以前のSDKと比較し、スッキリ書けるようになりました。進行状況もPipelineパッケージを使って、楽に取れるようになっています。ブロック分割のロジックを書く必要もなくなりました。ブロックサイズを指定すればOK。

ちなみにファイルサイズがブロックサイズで割り切れると最終ブロックの転送がエラーになるバグを見つけたのですが、修正してもらったので、次のリリースでは解決していると思います。

ふたつめの理由: レガシー対応

Blobのアップロードが目的であれば、Azure CLIをインストールすればOK。以上。なのですが、残念ながらそれができないケースがあります。

たとえば。Azure CLI(2.0)はPythonで書かれています。なので、Pythonのバージョンや依存パッケージの兼ね合いで、「ちょっとそれウチのサーバーに入れるの?汚さないでくれる?ウチはPython2.6よ」と苦い顔をされることが、あるんですね。気持ちはわかります。立場の数だけ正義があります。Docker?その1歩半くらい前の話です。

ですが、オンプレのシステムからクラウドにデータをアップロードして処理したい、なんていうニーズが急増している昨今、あきらめたくないわけであります。どうにか既存環境に影響なく入れられないものかと。そこでシングルバイナリーを作って、ポンと置いて、動かせるGoは尊いわけです。

ファイルのアップロードだけでなく、Azureにちょっとした処理を任せたい、でもそれはいじりづらいシステムの上なのねん、って話は、結構多いんですよね。ということでシングルバイナリーを作って、ポンと置いて、動かせるGoは尊いわけです。大事なことなので2回書きました。

C#やNode、Python SDKと比較してGoのそれはまだ物足りないところも多いわけですが、今後注目ということで地道に盛り上がっていこうと思います。

13 Oct 2017, 14:30

自動化を愛するWindows使いへ Boxstarterのすすめ

Windowsのセットアップどうする問題

そろそろFall Creators Updateが来ますね。これを機にクリーンインストールしようか、という人も多いのではないでしょうか。端末って使っているうちに汚れていく宿命なので、わたしは定期的に「こうあるべき」という状態に戻します。年に2~3回はスッキリしたい派なので、アップデートはいいタイミングです。

でもクリーンインストールすると、設定やアプリケーションの導入をGUIでやり直すのが、すこぶるめんどくせぇわけです。自動化したいですね。そこでBoxstarterをおすすめします。便利なのに、意外に知られていない。

Boxstarter

わたしはマイクロソフトの仲間、Jessieのポストで知りました。サンクスJessie。

Boxstarterで出来ること

  • シンプルなスクリプトで
    • Windowsの各種設定
    • Chocolateyパッケージの導入
  • 設定ファイルをネットワーク経由で読み込める
    • Gistから
  • ベアメタルでも仮想マシンでもOK

実行手順

手順はBoxstarterのサイトで紹介されています。

  • スクリプトを作る
  • Gistに上げる
  • Boxstarterを導入する

PowerShell 3以降であれば

. { iwr -useb http://boxstarter.org/bootstrapper.ps1 } | iex; get-boxstarter -Force
  • Gist上のスクリプトを指定して実行する

なお2017/10/13時点で、Boxstarterサイトのサンプルにはtypoがあるので注意 (-PackageNameオプション)

Install-BoxstarterPackage -PackageName "https://gist.githubusercontent.com/ToruMakabe/976ceab239ec930f8651cfd72087afac/raw/4fc77a1d08f078869962ae82233b2f8abc32d31f/boxstarter.txt" -DisableReboots

以上。

サンプルスクリプト

スクリプトはこんな感じに書きます。

ちなみに、わたしの環境です。こまごまとした設定やツールの導入はもちろん、Hyper-Vやコンテナ、Windows Subsystem for Linuxの導入も、一気にやっつけます。

# Learn more: http://boxstarter.org/Learn/WebLauncher

# Chocolateyパッケージがないもの、パッケージ更新が遅いものは別途入れます。メモです。
# Install manually (Ubuntu, VS, snip, Azure CLI/PS/Storage Explorer, Terraform, Go, 1Password 6, Driver Management Tool)

#---- TEMPORARY ---
Disable-UAC

#--- Fonts ---
choco install inconsolata
  
#--- Windows Settings ---
# 可能な設定はここで確認 --> [Boxstarter WinConfig Features](http://boxstarter.org/WinConfig)
Disable-GameBarTips

Set-WindowsExplorerOptions -EnableShowHiddenFilesFoldersDrives -EnableShowFileExtensions
Set-TaskbarOptions -Size Small -Dock Bottom -Combine Full -Lock

Set-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name NavPaneShowAllFolders -Value 1

#--- Windows Subsystems/Features ---
choco install Microsoft-Hyper-V-All -source windowsFeatures
choco install Microsoft-Windows-Subsystem-Linux -source windowsfeatures
choco install containers -source windowsfeatures

#--- Tools ---
choco install git.install
choco install yarn
choco install sysinternals
choco install 7zip

#--- Apps ---
choco install googlechrome
choco install docker-for-windows
choco install microsoft-teams
choco install slack
choco install putty
choco install visualstudiocode

#--- Restore Temporary Settings ---
Enable-UAC
Enable-MicrosoftUpdate
Install-WindowsUpdate -acceptEula

便利。

ちなみにわたしはドキュメント類はOneDrive、コードはプライベートGit/GitHub、エディタの設定はVisual Studio Code Settings Sync拡張を使っているので、Boxstarterと合わせ、 環境の再現は2~3時間もあればできます。最近、バックアップからのリストアとか、してないです。

新しい端末の追加もすぐできるので、物欲が捗るという副作用もあります。