しばたテックブログ

気分で書いている技術ブログです。

Windows 10でPowerShell Remoting over SSHを試す

【2017/10/25追記】

先日リリースされた、Fall Creators Update(1709)でPowerShell Remoting over SSHができなくされていました。
これまで利用可能だったのが間違った更新なのか、単純に一時的な使用不可なのかはよくわかりません...

【追記ここまで】


公式のアナウンスなどは全く無く、いつの間にかWindows 10 Creators Update(1703)でPowerShell Remoting over SSHが使える様になっていたので試してみました。

PowerShell Remoting over SSHについて

PowerShell Remoting over SSHとは何ぞやといった話はこちらのエントリをご覧ください。

blog.shibata.tech

どのPowerShellで使えるのか?

当初PowerShell Remoting over SSHはPowerShell 6.0向けの機能として発表され、現在も絶賛開発中です。
このためPowerShell Core 6.0であればこの機能はふつうに使えます。

で、他のバージョンに関してはいまのところWindows 10 Creators Update(1703)以降のWindows PowerShell 5.1にのみ実装された様です。
確認が取れなかったのでCreators Updateが出た直後のビルドから利用可能だったのかまでは不明ですが、少なくとも2017年8月現在のビルド(PSVersion = 5.1.15063.502)では利用可能になっています。

また、Windows PowerShell 5.1でもWindows Server 2016*1WMF 5.1として他のOSにインストールしたものに関しては利用できません。

PowerShell Remoting over SSHを試す

以前に試した時と同様にCentOSをサーバーとしてWindows 10から接続してみます。
CentOSのバージョンは7.3に上げています。

項目 Windows 10(1703) CentOS 7.3
基本設定 最新のWindows Updateを実施した状態 bento/centos7.3のBoxにyum updateを実施
IP - VirtualBoxのゲスト(localhostで接続する)
ユーザー - vagrant, root

1. CentOSの設定

CentOSの設定手順は前と同様ですが、PowerShellをyumからインストールする様に変更しています。
また/etc/ssh/sshd_configの設定をsedで行う様にしました。*2

# CentOS(Bash)
# PowerShell Core for Linuxのインストール
curl https://packages.microsoft.com/config/rhel/7/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo
sudo yum install -y powershell

# /etc/ssh/sshd_config の設定
# '# override default of no subsystems'のコメント行の下に設定を追加
# ※位置指定をかなり決め打ちにしているので注意
sudo sed -i.orig -e "/# override default of no subsystems/a Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile" /etc/ssh/sshd_config

# sshdの再起動
sudo systemctl restart sshd.service

2. Windowsの設定

PowerShell Remoting over SSHはPowerShellとOpenSSHを組み合わせた機能であるため、OpenSSHをインストールしてssh.exeのあるディレクトリに対してPATHを通しておく必要があります。

以下の手順でC:\Program Filesにインストールします。

# 要管理者権限
# OpenSSHのインストール
Invoke-WebRequest -Uri "https://github.com/PowerShell/Win32-OpenSSH/releases/download/v0.0.18.0/OpenSSH-Win64.zip" -OutFile "OpenSSH-Win64.zip"
Expand-Archive -Path ".\OpenSSH-Win64.zip" -DestinationPath "$env:ProgramFiles"

# Pathの追加
[Environment]::SetEnvironmentVariable('PATH', [Environment]::GetEnvironmentVariable('PATH') + ";$(Join-Path $env:ProgramFiles "OpenSSH-Win64")")

3. 接続確認

前と同様にNew-PSSessionおよびEnter-PSSessionを使用して接続確認をします。

PowerShell Remoting over SSHでは-HostName(-ComputerNameではない)や-UserNameパラメーターで接続先を指定します。*3

# セッション生成
# 検証環境の都合-HostNameがlocalhostになっているが実際には接続先のホスト名を指定する
$Session = New-PSSession -HostName "localhost" -UserName vagrant
# 接続
Enter-PSSession -Session $Session

下図の様にSSHのセッションが生成され問題なくCentOSのサーバーに接続できました。

f:id:stknohg:20170814171926p:plain

f:id:stknohg:20170814171940p:plain

ちなみに、OpenSSHをインストールせずに接続しようとすると以下の様なエラーになってしまいますので注意してください。

f:id:stknohg:20170814171908p:plain

制限事項

PowerShellのバージョンを問わず現時点のPowerShell Remoting over SSHの制限事項として接続先のポート指定ができません。

New-PSSessionには-Portパラメーターがあるのですが、これは通常のPSRemoting専用のパラメーターであり、PowerShell Remoting over SSHで使おうとすると不正なパラメーター扱いされエラーとなってしまいます。

この点に関しては以下のPull Requestが出ており目下対応中といったところなのでいずれ解消されると思います。

github.com

*1:先日提供されたInsider Preview版でも使えませんでした

*2:位置指定がかなり決め打ちなのであまり良いやり方ではないと思いますが楽だったのでつい...

*3:他に-KeyFilePathパラメーターもあります

Windows Serverに最小構成でRedmineをインストールする - その2

blog.shibata.tech

前回のエントリで最後に触れたとおりWindowsのThinでHTTPSアクセスを有効にする方法について説明します。

WindowsのEventMachineでSSLを有効にする方法

Thinの内部で利用されているEventMachineでSSLを有効にする方法については以下に詳しく記載されています。

github.com

github.com

これらの内容を基にいろいろ試してみた結果、現在のバージョンVer. 1.2.5においては以下の様にすれば良いことが分かりました。

  1. OpenSSLは最新版のVer.1.1.0系ではなく、Ver.1.0.2系を使う

    • ネイティブコンパイルに必要なライブラリの構成が1.1.0系だと駄目だそうです。
  2. ネイティブコンパイルのオプションに--with-opt-lib--with-ssl-includeを付ける

    • --with-ssl-dirパラメーターではダメな様です。
  3. プラットフォームの指定をrubyにする

    • デフォルトのプラットフォームはx64-mingw32ですがこれだと上手くいきませんでした...

gem installコマンドだと以下の様な指定になります。

gem install eventmachine --platform ruby -- --with-opt-lib=[OpenSSLのインストール先\bin] --with-ssl-include=[OpenSSLのインストール先\include]

このため、Redmine(Thin)のインストールにおいてHTTPSアクセスを有効にするにはbundle installコマンドから上記と同等のインストールができれば良いのですが、私のRubyちからが低く、bundle configなどいろいろ試してみたのですが、結局どうすれば出来るのかわかりませんでした...

仕方ないので今回は一旦bundle exec install gemコマンドからEventMachineだけを別にインストールし、Redmine(Thin)で使われているものと差し替えることでHTTPSアクセスを有効にすることとしました。

0. はじめに

前提条件

今回の作業を行う前提として、前回の手順でRedmineをインストールした直後の状態からスタートします。

Windowsサービスの設定

本エントリの作業ではWindowsサービスを設定しなおす必要があるので、一旦インストールしたサービスの登録を解除しておきます。

$REDMINE_SERVICE_NAME = "Redmine"

# Windowsサービスの解除
Stop-Service $REDMINE_SERVICE_NAME
thin_service remove -N $REDMINE_SERVICE_NAME

1. OpenSSLのインストール

OpenSSLのインストール

最初に触れた様にOpenSSLのVer.1.0.2系、現時点の最新版であるVer.1.0.2Lをインストールします。
ネイティブコンパイル用にインクルードファイルなども必要なので、LightではないWin64 OpenSSL v1.0.2Lをダウンロードしてインストールします。

前回同様サイレントインストールします。
インストール先はC:\OpenSSL-Win64としています。

$OPENSSL_INSTALL_PATH = 'C:\OpenSSL-Win64'
# ダウンロード
Invoke-WebRequest -Uri "http://slproweb.com/download/Win64OpenSSL-1_0_2L.exe" -OutFile "$(Get-Location -PSProvider Filesystem)\Win64OpenSSL-1_0_2L.exe"
# インストール
Start-Process -FilePath ".\Win64OpenSSL-1_0_2L.exe" -ArgumentList @("/SILENT", "/DIR=""$OPENSSL_INSTALL_PATH""") -Wait -PassThru

サーバー証明書の作成

こちらは無くてもなんとかなるのですが一応サーバー証明書も作っておきます。
手順と証明書の内容はかなり適当です。

実環境では適宜まともな証明書を使用してください。

# 必要なPATHを追加
$env:OPENSSL_CONF = Join-Path $OPENSSL_INSTALL_PATH "bin\openssl.cfg"
$env:PATH = "$(Join-Path $OPENSSL_INSTALL_PATH "bin");" + $env:PATH

# 証明書の設定は適当(CNだけ設定)なので必要に応じて変更してください 
openssl genrsa -out server.key 4096
openssl req -new -x509 -days 3650 -key server.key -out server.crt -subj "/C=JP/ST=/L=/O=/OU=/CN=$(hostname)"

作成した証明書は任意のディレクトリに配置してください。*1

2. SSL対応したEventMachineのインストール

続けてSSL対応したEventMachineをインストールします。

2-1. SSL対応したEventMachineのインストール

bundle execコマンドを使用してRedmineで使用しているものとは別にEventMachineをインストールします。
Redmineをインストールしたディレクトリに移動して以下のコマンドを実行してください。

$REDMINE_VER = '3.4.2'
$REDMINE_INSTALL_ROOT = 'C:\'
$REDMINE_INSTALL_PATH = Join-Path $REDMINE_INSTALL_ROOT "redmine-$REDMINE_VER"

# ディレクトリ移動
cd $REDMINE_INSTALL_PATH

# bundle exec gem install で個別にeventmachineをインストール
bundle exec gem install install eventmachine --platform ruby -- --with-opt-lib="$(Join-Path $OPENSSL_INSTALL_PATH "bin")" --with-ssl-include="$(Join-Path $OPENSSL_INSTALL_PATH "include")"

ここでエラー無くGemのインストールが完了すれば、BundlerのGemフォルダには以下の様に2つのEvenetMachineがインストールされているはずです。

f:id:stknohg:20170813000646p:plain

それぞれ、

  • eventmachine-1.2.5

    • 今回の手順でインストールされたEventMachine。SSL対応。
  • eventmachine-1.2.5-x64-mingw32

    • 前回のbundle installでインストールされたEventMachine。SSL非対応。

となります。

2-2. Redmineで使用しているEventMachineと差し替える

続けて、この2つのGemの名称を差し替えて、Redmine(Thin)でSSLに対応したEventMachineを使う様にしてやります。
単純にフォルダ名をリネームして差し替えてやります。

# フォルダ名の差し替え
$BUNDLE_GEM_ROOT = Join-Path $REDMINE_INSTALL_PATH "vendor\bundle\ruby\2.3.0\gems"
Move-Item (Join-Path $BUNDLE_GEM_ROOT "eventmachine-1.2.5-x64-mingw32") (Join-Path $BUNDLE_GEM_ROOT "eventmachine-1.2.5-x64-mingw32.orig")
Move-Item (Join-Path $BUNDLE_GEM_ROOT "eventmachine-1.2.5") (Join-Path $BUNDLE_GEM_ROOT "eventmachine-1.2.5-x64-mingw32")

f:id:stknohg:20170813000700p:plain

上図の様になっていれば完了です。

2-3. 動作確認

前回同様に動作確認を必要に応じて行ってください。

今回はHTTPSアクセスを有効にするので、--ssl--ssl-key-file--ssl-cert-fileパラメーターを指定してやります。
サーバー証明書はRedmineをインストールしたディレクトリにおいてあるものとします。

# 動作確認のため、必要に応じて実行する
# https://localhost:3000/ にアクセスして動作を確認する
bundle exec thin start -e production -p 3000 -a 0.0.0.0 -c "$REDMINE_INSTALL_PATH" --ssl --ssl-key-file "$(Join-Path $REDMINE_INSTALL_PATH "server.key")" --ssl-cert-file "$(Join-Path $REDMINE_INSTALL_PATH "server.crt")"

3. Windowsサービスの設定

動作確認に問題がないことを確認したら、最後にthin_serviceコマンドを使い、Redmine(Thin)をWindowsサービス化します。
--ssl--ssl-key-file--ssl-cert-fileパラメーターを指定する点以外は前回と同じです。

# サービス登録
$REDMINE_SERVICE_NAME = "Redmine"
$REDMINE_INSTALL_PORT = 3000
thin_service install -N $REDMINE_SERVICE_NAME -c "$REDMINE_INSTALL_PATH" -p $REDMINE_INSTALL_PORT -e production --ssl --ssl-key-file "$(Join-Path $REDMINE_INSTALL_PATH "server.key")" --ssl-cert-file "$(Join-Path $REDMINE_INSTALL_PATH "server.crt")"
# サービス起動
Start-Service Redmine

以上でインストールは完了です。
https://localhost:[$REDMINE_INSTALL_PORTのポート番号]/にアクセスしてRedmineにHTTPSアクセスができることを確認してください。

f:id:stknohg:20170813000716p:plain

f:id:stknohg:20170813000726p:plain

最後に

とりあえずこんな感じです。
bundle installで上手くやる方法がありましたらぜひ教えてください。

*1:今回の手順ではRedmineをインストールしたディレクトリに配置した例を挙げています

Windows Serverに最小構成でRedmineをインストールする

WindowsにRedmineをインストールする方法としてはBitnami Redmine Installerを使うのがメジャーですが、個人的な要件でできるだけ最小構成にしたく、MySQLを使わずにSQLiteを、Apacheも使いたくなかったので幾つかのサイトを参考にして自力でインストールを試みました。

0. はじめに

参考サイト

本エントリは以下のサイトの手順を参考にしました。

検証環境

検証環境は以下となります。

  • Windows Server 2012 R2

    • インストール直後の状態に最新のWindows Updateを適用した状態
  • Windows PowerShell 4.0

    • デフォルトでインストールされているPowerShellをそのまま使います

前回のエントリの構成と同じです。

また、インストールするするRedmineのバージョンは現時点の最新のVer.3.4.2としました。

【2017/08/17 追記】

Windows Server 2016 + PowerShell 5.1の環境でも本手順が動作することを確認しました。

【追記ここまで】

1. Ruby(RubyInstaller)のインストール

rubyinstaller.org

Redmine 3.4.2ではNokogiri 1.7.2が使われており、これがRuby 2.4系に対応していなかったため今回はRuby 2.3.3(64bit版)をインストールします。

GUIのインストーラーからインストールしても構わないのですが、面倒なのでPowerShellから以下のコマンドでサイレントインストールします。

$RUBY_VER = '2.3.3'
$RUBY_INSTALL_PATH = 'C:\Ruby23-x64'
# ダウンロード
Invoke-WebRequest -Uri "https://dl.bintray.com/oneclick/rubyinstaller/rubyinstaller-$RUBY_VER-x64.exe" -OutFile "$(Get-Location -PSProvider Filesystem)\rubyinstaller-$RUBY_VER-x64.exe"
# インストール
Start-Process -FilePath ".\rubyinstaller-$RUBY_VER-x64.exe" -ArgumentList @("/dir=""$RUBY_INSTALL_PATH""", '/silent', '/tasks="addtk,modpath"', '/lang=ja') -Wait -PassThru

# PowerShellを再起動しない場合はPATHを追加しておく
$env:PATH = "$(Join-Path $RUBY_INSTALL_PATH "bin");" + $env:PATH

Rubyのインストールオプションは以下となります。

  • インストール先 : C:\Ruby23-x64
  • インストールオプション :
    • Tcl/Tkのサポートをインストールする
    • Rubyの実行ファイルパスをPATH環境変数に追加

続けてDevelopment Kitをインストールします。
以下のコマンドを実行してC:\MinGWに展開しておきます。

# Development Kit(Ruby 2.0~2.3向け)のインストール
$RUBY_DEVKIT_INSTALL_PATH = 'C:\MinGW'

# ダウンロード
Invoke-WebRequest -Uri "https://dl.bintray.com/oneclick/rubyinstaller/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" -OutFile "$(Get-Location -PSProvider Filesystem)\DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe"

# 解凍+展開
Start-Process -FilePath ".\DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe" -ArgumentList @("-o""$RUBY_DEVKIT_INSTALL_PATH""", "-y") -Wait -PassThru

# Gemのインストールに必要なためPATHを追加しておく
$env:PATH = "$(Join-Path $RUBY_DEVKIT_INSTALL_PATH "bin");$(Join-Path $RUBY_DEVKIT_INSTALL_PATH "mingw\bin");" + $env:PATH

以上でRubyとDevelopment Kitのインストールは完了です。

2. Redmineのインストール

2-1. Redmineのダウンロードと解凍

ここからRedmine 3.4.2のインストールを行います。
以下のコマンドでC:\redmine-3.4.2にソースを展開します。

$REDMINE_VER = '3.4.2'
$REDMINE_INSTALL_ROOT = 'C:\'
$REDMINE_INSTALL_PATH = Join-Path $REDMINE_INSTALL_ROOT "redmine-$REDMINE_VER"

# Zipのダウンロード
Invoke-WebRequest -Uri "http://www.redmine.org/releases/redmine-$REDMINE_VER.zip" -OutFile "$(Get-Location -PSProvider Filesystem)\redmine-$REDMINE_VER.zip"

# PowerShell 4.0だとZipを扱えないのでRubyで頑張って解凍する
# ※いったんカレントディレクトリに解凍してから移動している
gem install rubyzip --no-rdoc --no-ri
ruby -e "require 'zip'; Zip::File.open('.\redmine-$REDMINE_VER.zip') do |zip| zip.each do |entry| puts \""entry #{entry.name}\""; zip.extract(entry, entry.name) { true } end; end"
Move-Item ".\redmine-$REDMINE_VER" $REDMINE_INSTALL_ROOT -Force

ちなみに、Zipの解凍についてはPowerShell 5.0以降であればExpand-Archiveコマンドが使えます。

# PS 5.0以降ならExpand-Archiveで解凍可能
Expand-Archive -LiteralPath "$(Get-Location -PSProvider Filesystem)\redmine-$REDMINE_VER.zip" -DestinationPath $REDMINE_INSTALL_ROOT

2-2. 事前準備

ここで先にconfig/database.ymlを設定します。
今回は最小構成にしたいのでSQLiteにします。

# config/database.yml を設定。SQLiteを使用する。
@"
# SQLite3 configuration
production:
  adapter: sqlite3
  database: db/redmine.sqlite3
"@ -replace "`n","`r`n" | Set-Content (Join-Path $REDMINE_INSTALL_PATH "config\database.yml") -Encoding Default

また、アプリケーションサーバーにThin 1.7.2を使用したいので、Gemfile.localを作成しRedmineで使用するGemをカスタマイズします。

# Gemfile.local を設定。thinを使う設定を追加。
@"
gem "thin", "1.7.2"
"@ -replace "`n","`r`n" | Set-Content (Join-Path $REDMINE_INSTALL_PATH "Gemfile.local") -Encoding Default

2-3. インストール作業

ここから本格的に設定を開始します。
セットアップのためのBundlerとThinをWindowsサービス化するためにthin_serviceをインストールします。

# 事前に必要なGemのインストール
# ※thin_serviceはbundle installでは正常に動作しなかったためgem installにしている
gem install bundler --no-rdoc --no-ri
gem install thin_service --no-rdoc --no-ri

続けてRedmineを展開したディレクトリに移動してbundleコマンドを実行していきます。

# ディレクトリ移動
cd $REDMINE_INSTALL_PATH

# 64bit版のためImageMagic抜きで(--without rmagick)bundle install
bundle install --without development test rmagick --path vendor/bundle

# セッション改ざん防止用秘密鍵の作成
bundle exec rake generate_secret_token

# データベースのマイグレーション
bundle exec rake db:migrate RAILS_ENV="production"

# 初期データのロード
bundle exec rake redmine:load_default_data RAILS_ENV="production" REDMINE_LANG="ja"

2-4. 動作確認

ここで動作確認のためにThinをコマンドラインから起動します。
こちらは必要に応じて行ってください。

# 動作確認のため、必要に応じて実行する
# http://localhost:3000/ にアクセスして動作を確認する
bundle exec thin start -e production -p 3000 -a 0.0.0.0 -c "$REDMINE_INSTALL_PATH"

もしThinの起動に失敗する場合はwebrickで確認してみるのも良いでしょう。

# 動作確認のため、必要に応じて実行する
# http://localhost:3000/ にアクセスして動作を確認する
bundle exec rails server webrick -e production

2-5. Windowsサービスの設定

動作確認に問題がないことを確認したら、最後にthin_serviceコマンドを使い、Redmine(Thin)をWindowsサービス化します。

# サービス登録
$REDMINE_SERVICE_NAME = "Redmine"
$REDMINE_INSTALL_PORT = 3000
thin_service install -N $REDMINE_SERVICE_NAME -c "$REDMINE_INSTALL_PATH" -p $REDMINE_INSTALL_PORT -e production
# サービス起動
Start-Service Redmine

外部からアクセスする必要がある場合はFirewallのポートを開けておきます。

# ポート開放
New-NetFirewallRule -DisplayName $REDMINE_SERVICE_NAME -Group "Redmine" -Direction Inbound -Protocol Tcp -LocalPort $REDMINE_INSTALL_PORT -Action Allow

以上でインストールは完了です。
http://localhost:[$REDMINE_INSTALL_PORTのポート番号]/にアクセスすればRedmineがふつうに使えます。

f:id:stknohg:20170808212404p:plain

f:id:stknohg:20170808212419p:plain

注意事項

今回の手順ではRedmineに対してHTTPのみ利用可能でHTTPSでアクセスすることができません。

通常ThinでHTTPSアクセスするには起動時の引数に--sslを付ければよいのですが、今回の環境では--sslを付けて起動しても、HTTPSでアクセスされたときにThin内部で利用してるEventMachineが以下の様なエラーを吐いてしまいます。

terminate called after throwing an instance of 'std::runtime_error'  
what():  Encryption not available on this event-machine

f:id:stknohg:20170808213030p:plain

HTTPSアクセスするための方法は次のエントリで紹介します。

blog.shibata.tech