A certain engineer "COMPLEX"

開発メモ その179 Lenovo Chromebook S330にUbuntu18.04をインストールしSSHで接続

Introduction


Lenovo Chromebook S330は、フルキーボード、広いタッチパッド、豊富なインターフェースを備えたパワフルな14型のChromebookです。

こんなのを購入して遊んでいます。

ベースはLinuxなので遊びたいのですが、Chromebookへの接続はいろいろ制限されています。
例えば、Teamviewerはクライアント専用。これは面白くないです。

なので、仮想OSとしてUbuntu 18.04をインストールし遊んでみます。

Install Ubuntu


まずは仮想OSのインストール。

デベロッパーモードで起動

ESCキーとF3 (再読込ボタン) を押しながら電源を入れ、Ctrl+D を押してデベロッパーモードで起動。
ローカルのデータが消えますので購入直後に実施しましょう。

croutonをインストール

croutonは、ChromeBookにLinux環境を構築するためのツール。

Chromium OS Universal Chroot Environment. Contribute to dnschneid/crouton development by creating an account on GitHub.

Chromeブラウザを起動しアドレスバーに https://goo.gl/fd3zc と入力し保存します。
省略アドレスで、https://raw.githubusercontent.com/dnschneid/crouton/master/installer/croutonにリダイレクトされます。

Ubuntu 18.04をインストール

Ctrl+Alt+Tでターミナルタブを開きます。
シェルに切り替えるために


$ shell

と入力します。

続いて、ダウンロードしたcroutonを使い、インストールを行います。


$ sudo sh ~/Downloads/crouton -r bionic -t gnome-desktop

実行するとインストールが始まります。
しばらくすると、インストールしたUbuntuに追加するユーザ名とパスワードを聞かれます。

Ubuntu 18.04を起動

ターミナルタブから


$ sudo startgnome

これでUbuntuに切り替わります。
Chrome OSに戻りたい場合は、Ctrl+Alt+Shift+F1で戻ります。
停止するなら、ターミナル上でCtrl+Cで停止できます。

Install sshd


Ubuntuにsshdをインストールします。
まずターミナルを起動します。
Activityからterminalと入力します

インストール

ターミナルから


$ sudo apt update
$ sudo apt upgrade
$ sudo apt install -y ssh iptables net-tools

として必要なパッケージをインストールしておきます。
net-toolsはなくてもよいですが、通信状況とかを把握したいなら必須です。

ファイアウォールの変更

ターミナルから /etc/rc.local を作成し、変更をします。


$ sudo vi /etc/rc.local

下記の内容を追加します。


/sbin/iptables -P INPUT ACCEPT

この内容はすべてのインバウンド通信を許可するなので不安なら


/sbin/iptables -I INPUT -p tcp --dport 22 -j ACCEPT

とします。

sshd自動起動設定

続いて、/etc/rc.local に下記の内容を追加します。


mkdir -p -m0755 /var/run/sshd
/usr/sbin/sshd

そして、保存を行い、


$ sudo chmod 755 /etc/rc.local
$ ls -la /etc/rc.local
-rwxr-xr-x. 1 root root 115 Aug 13 04:10 /etc/rc.local

実行権限を付与します。

鍵の生成

SSHの接続に必要なホストの秘密鍵、公開鍵を生成します。


$ sudo ssh-keygen -A
$ ls -la /etc/ssh
total 596
drwxr-xr-x. 2 root root 4096 Aug 13 04:18 .
drwxr-xr-x. 120 root root 4096 Aug 13 04:16 ..
-rw-r--r--. 1 root root 553122 Mar 4 21:17 moduli
-rw-r--r--. 1 root root 1580 Mar 4 21:17 ssh_config
-rw-r--r--. 1 root root 3264 Mar 4 21:17 sshd_config
-rw-------. 1 root root 668 Aug 13 04:18 ssh_host_dsa_key
-rw-r--r--. 1 root root 604 Aug 13 04:18 ssh_host_dsa_key.pub
-rw-------. 1 root root 227 Aug 13 04:16 ssh_host_ecdsa_key
-rw-r--r--. 1 root root 176 Aug 13 04:16 ssh_host_ecdsa_key.pub
-rw-------. 1 root root 411 Aug 13 04:16 ssh_host_ed25519_key
-rw-r--r--. 1 root root 96 Aug 13 04:16 ssh_host_ed25519_key.pub
-rw-------. 1 root root 1679 Aug 13 04:16 ssh_host_rsa_key
-rw-r--r--. 1 root root 396 Aug 13 04:16 ssh_host_rsa_key.pub
-rw-r--r--. 1 root root 338 Aug 13 04:16 ssh_import_id

実行権限を付与します。

sshd起動

一度手動で起動してみます。


$ sudo /sbin/iptables -P INPUT ACCEPT
$ sudo mkdir -p -m0755 /var/run/sshd
$ sudo /usr/sbin/sshd
$ ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 5 127.0.0.1:30001 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*

起動が確認できれば、ChromeOSに戻ってUbuntuを停止、再度起動した後でも自動でsshdが起動します。
そして、外部からsshで接続してみます。


$ ssh hogehoge@192.168.11.XX
hogehoge@192.168.11.XX's password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 3.18.0-19346-g9ff80f5e4c97 aarch64)


* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage


0 packages can be updated.
0 updates are security updates.


Your Hardware Enablement Stack (HWE) is supported until April 2023.
Last login: Tue Aug 13 04:48:22 2019 from 192.168.11.YY
(bionic)hogehoge@localhost:~$

きちんと、aarch64のUbuntuにつながっていることがわかります。

開発メモ その178 Git LFSで巨大なファイルをpushすると i/o timeout

Introduction


こんな感じのエラーがでました。


LFS: Put https://hogehoge:12345/test/sample.git/gitlab-lfs/objects/e14f763270cf193d0b5f74b169f44157a4b0c6efa708f4dd0ff78ee691763bcb/1999639040: read tcp [240b:251:2640:1600:a92c:da86:91c8:8cc5]:45540->[240b:251:2640:1600:211:32ff:fe6d:4a4b]:61792: i/o timeout
error: failed to push some refs to 'https://hogehoge:12345/test/sample.git'

How to resolve?


タイムアウト値の延長またはタイムアウトを無効にします。
ユーザー全体なら--globalをつけます。

無効


> git config lfs.activitytimeout 0

X 秒に延長

数字の単位は秒。下記は30秒。


> git config lfs.activitytimeout 30

開発メモ その177 Visual Studio Code Remote SSHでつながらない

Introduction


メモ。

Why?


ssh.config の場所が悪い

接続に失敗した際、出力コンソールに下記のようなログが出ていました。


remote-ssh@0.44.0
win32 x64
SSH Resolver called for "ssh-remote+7b22686f73744e616d65223a223139322e3136382e31312e31315b5562756e74755f31382e30342e325f4c54535d222c2275736572223a22742d74616b6575636869227d", attempt 1
SSH Resolver called for host: t-takeuchi@192.168.11.11[Ubuntu_18.04.2_LTS]
Setting up SSH remote "192.168.11.11[Ubuntu_18.04.2_LTS]"
Using commit id "0f3794b38477eea13fb47fbe15a42798e6129338" and quality "stable" for server
Testing ssh with ssh -V
ssh exited with code: 0
Got stderr from ssh: OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
Using SSH config file "C:\Users\TAKUYA\Dropbox\Settings\Visual Studio Code\Remote Development\ssh.config"
Install and start server if needed
> Can't open user config file C:\\XXXX\\Visual: No suc
> h file or directory
> プロセスが、存在しないパイプに書き込もうとしました。
>
"install" terminal command done
Received install output: プロセスが、存在しないパイプに書き込もうとしました。
Failed to parse remote port from server output: プロセスが、存在しないパイプに書き込もうとしました。

ログを書き込もうとしたら、書き込みに失敗したもよう。
原因がssh.configをおいたパスに空白が含まれている、ということ。

それくらい対処してくださいよ、Microsoftさん。

Windowsの環境変数なんてしらない


remote-ssh@0.44.0
win32 x64
SSH Resolver called for "ssh-remote+192.168.11.11", attempt 1
SSH Resolver called for host: 192.168.11.11
Setting up SSH remote "192.168.11.11"
Using commit id "0f3794b38477eea13fb47fbe15a42798e6129338" and quality "stable" for server
Testing ssh with ssh -V
ssh exited with code: 0
Got stderr from ssh: OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
Using SSH config file "C:\XXXX\ssh.config"
Install and start server if needed
>
> percent_expand: unknown key %U
> プロセスが、存在しないパイプに書き込もうとしました。
>
"install" terminal command done
Received install output: プロセスが、存在しないパイプに書き込もうとしました。
Failed to parse remote port from server output: プロセスが、存在しないパイプに書き込もうとしました。

ssh.confgで秘密鍵のファイルパスに環境変数%USERPROFILE%を使おうとしたためです。
環境変数は使わないほうがよいでしょう。

OSXにつながらない


remote-ssh@0.44.0
win32 x64
SSH Resolver called for "ssh-remote+7b22686f73744e616d65223a224d61634d696e69283139322e3136382e31312e3829227d", attempt 1
SSH Resolver called for host: MacMini(192.168.11.8)
Setting up SSH remote "MacMini(192.168.11.8)"
Using commit id "0f3794b38477eea13fb47fbe15a42798e6129338" and quality "stable" for server
Testing ssh with ssh -V
ssh exited with code: 0
Got stderr from ssh: OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
Using SSH config file "C:\XXXX\ssh.config"
Install and start server if needed
>
> Password:
"install" wrote data to terminal: "**********"
>
>
> sed: 1: "s/^linux //gi": bad flag in substitute command: 'i'
> Unsupported architecture:
> a223db13-3bae-4f5f-ab69-b2f577125593##27##
>
"install" terminal command done
Received install output: a223db13-3bae-4f5f-ab69-b2f577125593##27##
Unsupported architecture
The remote server architecture is not supported
------

OSXはFrerBSDの派生です。
sedコマンドはFreeBSDとLinuxではコマンドが異なります。
公式を確認してもOSXが使えない、という表記が見つかりませんでしたが、おそらくダメでしょう。

開発メモ その176 Docker Jenkins in Synology NAS

Introduction


JenkinsをSynology NASに構築したのでメモ。
Slaveノードは別マシンに構築します。

How to?


用意するもの

jenkinsのディレクトリを用意します。
これらはdockerコンテナにマウントされます。
今回は下記をマウントします。

  • /docker/jenkins/jenkins_home
  • /docker/jenkins/share/jenkins
  • /docker/jenkins/share/jenkins/ref

そして権限を変更します。


$ sudo chown -R 1000 /volume1/docker/jenkins

Jenkinsのダウンロード

dockerの場合、コンテナ内のデータは破棄されてしまうため、Jenkins本体をマウントする形にすることでアップデートできるようにします。

Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software

Generic Java package (.war)をダウンロードし、Jenkins.war/docker/jenkins/share/jenkinsにコピーします。

キーストアの作成

HTTPSで接続するために作成します。既にLet's Encryptで証明書は発行済みであるものとします。
HTTPで良い場合は、必要ありません。

Javaをインストールする必要があるのでパッケージ センターからインストールします。

パッケージ センター

インストール後のパス

続いて、下記のシェルをsudoで実行します。


#!/bin/bash

KEYROOT=/usr/syno/etc/certificate/system/default
KEY_PEM=${KEYROOT}/privkey.pem
CERT_PEM=${KEYROOT}/cert.pem
JAVA_HOME=/var/packages/Java7/target/j2sdk-image/jre/bin
KEYSTORE=/volume1/docker/jenkins/jenkins_home/keystore

openssl rsa -des3 -in $KEY_PEM -out key.encrypted.pem
openssl pkcs12 -inkey key.encrypted.pem -in $CERT_PEM -export -out keys.encrypted.pkcs12
${JAVA_HOME}/keytool -importkeystore -srckeystore keys.encrypted.pkcs12 -srcstoretype pkcs12 -destkeystore $KEYSTORE

下記のように実行します。
パスワードの空文字は許容されません。


$ sudo ./generate_jenkins_keystore.sh
writing RSA key
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Enter pass phrase for key.encrypted.pem:
Enter Export Password:
Verifying - Enter Export Password:
Importing keystore keys.encrypted.pkcs12 to /volume1/docker/jenkins/keystore_...
Enter destination keystore password:
Re-enter new password:
Enter source keystore password:
Entry for alias 1 successfully imported.
Import command completed: 1 entries successfully imported, 0 entries failed or cancelled

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore /volume1/docker/jenkins/keystore_ -destkeystore /volume1/docker/jenkins/keystore_ -deststoretype pkcs12".

コンテナの作成

キーストア作成の時に入力したパスワードを指定してコンテナの起動を実行します。
ホスト側のポートは適宜変更します。
HTTPで良い場合は、--httpから始まる引数を削除します。


$ sudo docker run -v /volume1/docker/jenkins/jenkins_home:/var/jenkins_home \
-v /volume1/docker/jenkins/share/jenkins:/usr/share/jenkins \
-p 38080:8443 \
-p 50003:50000 \
--name jenkins \
jenkins/jenkins:alpine \
--httpPort=-1 \
--httpsPort=8443 \
--httpsKeyStore=/var/jenkins_home/keystore \
--httpsKeyStorePassword=

コンソールが流れてしばらくするとadminの初期パスワードが表示されますのでメモしておきます。


*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

b0c58624703945a3ba1517b556b0f1bc

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

初期設定

ブラウザからアクセスします。

Jenkinsのアンロック。メモした初期パスワードを入力

Jenkinsのアンロック

プラグインのインストール。Install suggested plugins を選択

インストール中

ユーザ登録。入力後、Save and Finish

準備完了

開発メモ その175 Docker Registry in Synology NAS

Introduction


Dockerイメージを保存するプライベートなDocker RegistryをSynology NASに構築したのでメモ。
Docker Registryもdockerコンテナとして動作します。

How to?


用意するもの

設定ファイル、イメージを格納するディレクトリを用意します。
これらはdockerコンテナにマウントされます。
今回は下記をマウントします。

  • /docker/registry/config/config.yml
  • /docker/registry/config/htpasswd
  • /docker/registry/images
  • /docker/registry/certs

/docker/registry/config/config.yml


version: 0.1
log:
fields:
service: registry
storage:
delete:
enabled: true # open delete api
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
auth:
htpasswd:
realm: basic-realm
path: /auth/htpasswd # use apache basic-auth

/docker/registry/config/htpasswd

registryへのログインパスワードを格納するファイルです。
下記のようにdockerコンテナに作らせます。


$ docker run --rm -ti xmartlabs/htpasswd > htpasswd

/docker/registry/images

dockerイメージの保存先です。
ただのフォルダです。

/docker/registry/certs

sslのための証明書、.crt、.keyを格納しておきます。
Let's Encryptが更新されたらここを更新します。

HTTPSでregistryにアクセスするのが基本です。ここを設定しなくても利用はできますが、dockerの設定で信頼できないregistryにアクセスできるよう設定を追加する必要があるので、ここはきちんと設定しておきます。

コンテナ作成

registryをpullします

pullできました

コンテナを作成します

詳細設定のボリューム

詳細設定のポート設定

詳細設定の環境

以上で完成です。

動作確認

コンテナを起動後、dockerからログインできるかどうかを確認します。
ポート番号を確認し下記のように確認しておきます。
usernameとpasswordは最初に作ったhtpasswdファイルで作成した情報になります。


> docker login https://hogehoge:28009/
Username: xxxxxx
Password:
Login Succeeded

もしssl設定をしていない場合は下記のようになりますので、クライアント側でdockerの設定を変更しておきます。


> docker login http://192.168.11.17:28009
Username: xxxxxx
Password:
Error response from daemon: Get https://192.168.11.17:28009/v2/: http: server gave HTTP response to HTTPS client