t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

PCケースの3.5インチベイに液晶ディスプレイを組込んでみた

サーバー機の3.5インチフロントベイが余っているので液晶ディスプレイを組み込んでみた。

横長のディスプレイを探したのだがちょうど良いサイズのものは製造されてなさそうなので以下を3つ並べている。

※基盤含めて縦幅が26ミリを超えると取り付けできないので部品の選定にかなり苦労した。

アイデアとしてはディスプレイの取り付け土台とモニタフレームを用意して濃黒の半透明アクリルパネルで基盤部分を覆い隠すことでディスプレイの光だけが見えるというもの。

ただ黒の半透明アクリルが一般的ではないのかAmazonで見つけられなかったので半透明アクリルに自動車のヘッドライト用減光シートで代用することにした。

綺麗に貼るためにヘラとフィルム貼りスプレー併せて調達

しかし初回はこのざまである。なかなか難しい。

何度か試してモニタフレームサイズの綺麗な箇所が作れたらバンドソーで切り出した。

2023年の1月に購入して1年間段ボールで眠っていたバンドソー。今更開梱して机にビスで固定しろと書かれてて絶望したけどちょうど良い木の板があったのでそれに固定して使った。※厚みのあるものを切るときは作業台とかに固定しないと危険だと思うので今後検討したい。

3Dプリントパーツの設計調整も試行錯誤の連続で苦労した。

最終的な設計はこんな感じ。

モニター土台のもう片方の固定パーツは挿し込んでからネジ止めするため、ヒートプレス機でインサートナットを埋め込んだ。

ハンダゴテでも出来るけど歪みなく作りたい場合は便利。

フレームとアクリルパネルは以下のボンドで接着した。PLAの接着にベストな接着剤については諸説あるけど力がかかる部品ではないのでヨドバシの文具コーナーで見つけたものを試した。PLAの表記はないけどアクリル◎とPP・PE・PET・ABSが◎となってたのが決め手。

Arduinoで実験中の様子。イメージ通り。

そして地獄の配線作業。ArduinoとディスプレイはSPIという方式で通信するのだが、通信の宛先を決めるChip Select線以外の電力線やデータ線は共通になっているので3台分をまとめることになる。パネルと本体の接続はシンプルにしたいのでパネル側であらかたまとめてしまうことにした。ケーブル2本を強引にかしめた部分がなかなかデュポン端子カバーに刺さらずに苦労した。

共通系が6本(GND・VCC・SCL・SDA・RES・DC)とCS線がそれぞれ1本で合計9本のラインで済むのでArduinoとの接続は10ピン用の端子カバーで綺麗にまとめられた。

また、今回はArduino Nano Everyを採用。USBは以下の製品を使ってマザーボードから直接接続する形とした。

組み込んでみたのがこちら。最初はArduino Unoで検討してたので専用の固定土台を設計しようかと思っていたけどNano Everyならマスキングテープで十分。見える場所ではないし。

ということで外装が完成。

ディスプレイ3台を更新するためのArduinoコードは次のとおり。

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

#define TFT_CS1        10
#define TFT_CS2        7
#define TFT_CS3        6

#define TFT_RST        9
#define TFT_DC         8

Adafruit_ST7735 tft[] = {
  Adafruit_ST7735(TFT_CS1, TFT_DC, TFT_RST),
  Adafruit_ST7735(TFT_CS2, TFT_DC, -1),
  Adafruit_ST7735(TFT_CS3, TFT_DC, -1)
};

typedef struct { 
  uint16_t color;
  String str;
  byte size;
} message;

message data[3][10];

void reset(int n){
  for(int i=1;i<10;i++){
    data[n][i]={0, "", 0};
  }
}

void setup(void) {
  Serial.begin(9600);
  for(int i=0;i<3;i++){
    reset(i);
    tft[i].initR(INITR_MINI160x80);
    tft[i].setRotation(3);
    tft[i].fillScreen(ST77XX_BLACK);
  }
}

void loop() {
  while (Serial.available() == 0) {
  }
  String s = Serial.readString();
  
  if(s.length()<12){
    Serial.println("NACK");
    return;
  }
  for(int i=0;i<12;i++){
    if(!isDigit(s.charAt(i))){
      Serial.println("NACK");
      return;
    }
  }
  Serial.println("ACK");

  int n = s.substring(0,1).toInt();
  if(n<3){
    data[n][s.substring(1,2).toInt()] = {
      RGB888_to_BGR565(
        byte(s.substring(3,6).toInt()),
        byte(s.substring(6,9).toInt()),
        byte(s.substring(9,12).toInt())
      ),
      s.substring(12),
      byte(s.substring(2,3).toInt())
    };
  } else if (n<6){
    n-=3;
    update_screen(tft[n], data[n]);
  } else if (n<9){
    n-=6;
    reset(n);
  }
}

uint16_t RGB888_to_BGR565(byte red, byte green, byte blue) {
  if(red>255){red=255;}
  if(green>255){green=255;}
  if(blue>255){blue=255;}
  uint16_t bgr565 = 0;
  bgr565 = blue>>3;
  bgr565 = bgr565<<6;

  bgr565 += green>>2;
  bgr565 = bgr565<<5;

  bgr565 += red>>3;
  return bgr565;
}

void update_screen(Adafruit_ST7735 tft, message *m) {
  tft.setTextWrap(false);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);

  for(int i=0;i<10;i++){
    tft.setTextColor(m[i].color);
    tft.setTextSize(m[i].size);
    tft.println(m[i].str);
  }
}

シリアル通信で受信した内容を12桁の固定長+可変長のフォーマットで解釈して指定のモニターの表示データを決める仕組みとなっている。

モニターは0~2番までの3台で、データを実際に反映する際はモニター番号に3を足した3~5を指定、データをクリアする場合はモニター番号に6を足した6~8を指定する。

データの解読が完了したらシリアル通信でACKという文字列、エラーならNACKを返す仕組み。
※ACK=Acknowledgement(了承)

実際に送るデータの例はこちら。

600000000000 Deletion
012255255255 CPU Temp
03412812812845 Deg
300000000000 Load

700000000000 Deletion
112255255255 HDD Usage
134255000000 5%
400000000000 Load

800000000000 Deletion
212255255255 Last Logon
232255128128 2024/01/18
500000000000 Load

Linux側からはAWS S3の使用量をあらかじめテキストファイルに保存する仕組みを作っているのでそのテキストから容量を所定のフォーマットにしてArduino側にシリアル通信で送る仕組みを作った。

#!/usr/bin/env python3
import time
import serial
f = open('/mnt/encrypted/Archive/s3usage.txt', 'r')
data = f.readlines()
usage = int(data[1].split(':')[1].strip())/1024**3
usage = round(usage, 5 - len(str(int(usage))))

ser = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(1.5)

ser.write("600000000000 Deletion".encode())
print(ser.readline().strip().decode())
ser.write("012255255255S3 Usage(GB)".encode())
print(ser.readline().strip().decode())
ser.write(("034128128128" + str(usage)).encode())
print(ser.readline().strip().decode())
ser.write("300000000000 Load".encode())
print(ser.readline().strip().decode())

ser.close()

※接続したArduinoはttyACM0というデバイスとして認識された。これは環境によるので注意。また、実行ユーザーをdialoutグループに追加しておかないとttyACM0へのアクセスが拒否されるため注意。

さて、これをcronジョブで任意の時間に実行すれば自動的にアップデートされるようになる。

ということで再度冒頭の写真。

3つのディスプレイのうちあと2つは今のところダミーのHDD容量と実際に更新される現在時刻が入ってるけどこんなところに時計要らないのでこれは変えるつもり。
何を表示させるかはこれから検討しようと思う。

以上。

waves 0.96インチ IPS 液晶ディスプレイのカラー指定で青・赤が逆になるBGR565形式だったため対処のメモ

前回こちらの記事で紹介したディスプレイについて、カラー指定の青と赤が逆になっていて困ったのでその修正方法についてメモしておく。
thom.hateblo.jp

ライブラリ「Adafruit_ST7735_and_ST7789_Library」に入っているサンプルコード「graphictest.ino」内に以下のようなコードがある。

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  //以下略

不思議な事にST77XX_REDと指定している部分は青文字でHello World!と表示され、ST77XX_YELLOWと指定しているところは水色でHello World!と表示される。ただ、ST77XX_GREENだけはちゃんと緑色で表示される。

定義がおかしいのかと思って確認してみた。Arduino IDE 2で右クリックして定義に飛ぶことが出来る。

そうすると次のようなコードが見つかる。

// Some ready-made 16-bit ('565') color settings:
#define ST77XX_BLACK 0x0000
#define ST77XX_WHITE 0xFFFF
#define ST77XX_RED 0xF800
#define ST77XX_GREEN 0x07E0
#define ST77XX_BLUE 0x001F
#define ST77XX_CYAN 0x07FF
#define ST77XX_MAGENTA 0xF81F
#define ST77XX_YELLOW 0xFFE0
#define ST77XX_ORANGE 0xFC00

見たことない形式だけどコメントのおかげでこれが16ビットカラーの指定だということが分かった。

一般的にパソコンやWebサイト等の色指定は24ビットとなっており、赤、緑、青をそれぞれ8諧調に分けてその組み合わせで表現される。

例えばArduino IDEのカラーであるブルーグリーンは次のような感じ。

これが16ビットになると赤と青が5諧調、緑だけは人間の感度が高いため6諧調という構成になるようだ。これがRGB565という形式。

ただ商品名にフルカラーモジュールってあるのにほんとに16ビットなのか?と調べたところ、商品名に65kとも書いてあり、調べると約65,000色という意らしい。
2進数で16ビットということは2の16乗で65,536種類の色を表現できるから概算で65kという略記になっているようだ。

で、なんで青が赤になるんだということで調べてみると、どうやらRGBのほかにBGRという方式もあるようで、このディスプレイはRGB565じゃなくてBGR565で指定するとうまくいくことが分かった。

24ビットならRとBを入れ替えるだけなので簡単なんだけど先ほどの図で示した通り16ビットだと切れ目が16進数の2~3桁目が赤と緑、緑と青の情報が混じっているのでちょっと面倒くさい。

そこで変換関数を作って対応することにした。
以下は24ビットのR・G・Bをそれぞれ10進数で受け取り、BGR565に変換する関数である。

uint16_t RGB888_to_BGR565(byte red, byte green, byte blue) {
  uint16_t bgr565 = 0;
  bgr565 = blue>>3;
  bgr565 = bgr565<<6;

  bgr565 += green>>2;
  bgr565 = bgr565<<5;

  bgr565 += red>>3;
  return bgr565;
}

仕組みとしてはこんな感じ。

1) blueを3ビット右にシフトすることで下位3ビットを削ったものをbgr565に代入
2) bgr565を左に6ビットシフトすることでgreenが入るスペースを作り、2ビット削ったgreenを足し合わせる
3) bgr565を左に5ビットシフトすることでredが入るスペースを作り、3ビット削ったredを足し合わせる

この関数は実際にテキストカラー指定に組み込んで使用した。

tft.setTextColor(RGB888_to_BGR565(0,109,112));

非力なArduinoで逐一演算させるのもどうかなとは思ったんだけどもともとプロセッサーはビットレベルの演算が大得意なのでこの程度の計算は朝飯前。私の用途ではテキストをたまに更新するくらいなので仮に遅延が起きているとしても気づかないレベルだった。

以上

Arduino UnoでWaves 0.96インチ IPS フルカラー液晶ディスプレイの使用する方法のメモ

Amazonでwaves 0.96インチ IPS 液晶ディスプレイ SPI 80x160ピクセル 65 k フルカラー モジュール ST7735を購入したので使い方を記録しておこうと思う。

かなり小さいので用途は限られるけど今回サーバーの3.5インチフロントベイが余っているのでそこに組み込めないか思案中。

物理的なサイズとケース等への組付け方法

寸法はこんな感じ。Amazonの写真説明にも寸法図があるけどちょっとごちゃごちゃしていたので自分が見やすいように整理した。

ネジは付属していないのでM2サイズのものを調達する。
表示領域の裏面に表面実装パーツが乘っているので平らな面に組み付ける場合はM2のナットやスペーサー、スタンドオフ等を用いることができる。

私の場合は今回このディスプレイを3つ使用して3.5インチベイに入れたいので3Dプリンターで土台を作成した。

あと、綺麗に見せるためのアイデアとして透明の1mmアクリル板に車のヘッドライト用の減光シートを貼り付けることで基盤を目立たなくしてLED光だけ見えるような仕組みを考えている。

(どうやって組み付けるかはまだ思案中)

Arduinoからの利用方法

使用するライブラリは「Adafruit_ST7735_and_ST7789_Library」。

サンプルからgraphictestを選択して改変していく。

ピン接続

接続ピンはコードから読み取ることになる。
今回はArduino Unoを使用するのでif文のelseの部分が該当する。

表記と接続先のた対応はこちら。

現物の接続図はこちら。

コードの修正

setup関数で使用するディスプレイに合わせてTFTディスプレイの初期化コードを選択する必要がある。
今回紹介したディスプレイの場合、デフォルトのtft.initR(INITR_BLACKTAB);をコメントに変更し、tft.initR(INITR_MINI160x80);のコメントを外して有効化する。

次にディスプレイの出力方向をあわせる。

セットアップ関数の中にSerial.println(F("Initialized"));というコードがあるのでその直前にtft.setRotation(3);を挿入する。

これで出力方向が基盤の向きと揃う。
縦で使いたい場合はそのままでも良い。0~3を指定可能なので他の方向が良ければ試してみると良いと思う。

あとはサンプルのうちやりたいことに近いコードを残して他を削除していじっていくだけ。

以上

Sambaサーバーの設定でハマったポイント等のまとめ

今回はSambaサーバーのセキュリティ設定で色々と苦労した点についてまた将来再構築したり障害復旧させてりするときのためにまとめておこうと思う。

個別の項目は都度調べればなんとでもなるんだけど、セキュリティの全体像が分からないとアクセス不可の原因を切り分けるのも難しいので図を描いてポイントを記録しておこうと思う。

1. Samba Shared Folder Access Control

注) Samba Shared Folder Access Controlという名前は他の制御と比べて自分が分かりやすいようにそう呼んでるだけなので一般的な呼称でないことに注意。
/etc/samba/smb.confの設定はこんな感じ。

[global]
	dos charset = CP932
	unix charset = UTF-8

	workgroup = WORKGROUP
	security = user

	interfaces = {ここにサーバーIP} 127.0.0.1
	bind interfaces only = yes
	socket address = {ここにネットワークアドレス}

	printcap name = /dev/null
	log level = 1

[Share]
	path = /mnt/encrypted/Share
	writeable = yes

[Archive]
	path = /mnt/encrypted/Archive
	writeable = no

ポイントはセクション名になっている[Share]や[Archive]がWindowsからみたときの共有名で、実際のpathのフォルダ名と同じでなくても良いということ。
セクションをコピペしてpathだけ変えてできたつもりになってたり、逆にセクション名だけ変えてpathの編集忘れというミスに注意。

設定を変更した場合はサービスを再起動して反映させる。

sudo systemctl restart smb.service

2. Samba Server

今回構築したサーバーでは以下記事のとおり暗号化RAIDを使用しているのでsmb.serviceの自動起動のタイミングでハマった。
thom.hateblo.jp

/mnt/encryptedのマウントが完了する前にsmb.serviceが自動起動してしまってsambaがエラーでフォルダアクセスできない。
簡易的な対処としてして自動起動ではなくrootユーザーのcrontabで起動させるようにした。

以下、smb.serviceの自動起動を無効化するコマンド。

sudo systemctl disable smb.service

以下はrootのcrontabに記述する内容。sudo suでrootになってからcrontab -eで編集した。

@reboot systemctl start smb.service

3. SE Linux

最近のLinuxではOSのファイル・フォルダーアクセス制御とは別にSE Linuxというセキュリティ強化機能が最初から導入され有効になっているケースが多い。
getenforceコマンドでステータスを確認でき、Enforcingと表示されたら有効になっている。
SE Linuxではどんなプロセスがどういうファイル・フォルダーにアクセス可能であるかをルール化しておくことができ、ルールに無いアクセスは却下される。

ルールに追記するのが本来のやり方だけど、フォルダーごとに手動でsamba_share_tタグをつけていく方法もある。(以下コマンド)

sudo chcon -t samba_share_t /mnt/encrypted/Archive

タグが付いたかどうかはls -Zコマンドで表示できる。

[thom@storage encrypted]$ ls -Z
unconfined_u:object_r:samba_share_t:s0 Archive
unconfined_u:object_r:samba_share_t:s0 Share

今回ハマった点としては暗号化処理で一時的にファイルの通り道となるsys_tmpフォルダーにsamba_share_tをつけ忘れたことで、sys_tmpで生成されたファイルを共有フォルダーに移してもWindows側から見えなくなったこと。

生成されたファイルは移動させる場合でも基本的には元親フォルダ―のタグを引き継いだままなのでSE Linuxによってsambaからのアクセスが拒否されているというのがWindowsで確認できない原因だった。

4. Linux Folder Access Control

注) Linux Folder Access Controlという名前は他の制御と比べて自分が分かりやすいようにそう呼んでるだけなので一般的な呼称でないことに注意。

ここでは曖昧な理解になりがちなファイルとフォルダーのアクセス権の関係性について説明しようと思う。
※一般的なAccess Controlの話(read/write/executeとowner/group/other)はLinux使ってたら耳タコなのであえて割愛。

特に分かりづらいのがとあるファイルやフォルダーが削除できるか・編集できるかという点である。

下図ではペンのアイコンに斜線が入ったものが書き込み不可に設定してあるとする。

上記の設定においてそれぞれのファイル・フォルダーに実際に行える操作は次のとおりである。

例えば、ファイルEは書き込み可能なのに削除できない、ファイルGは編集できないのに削除はできるというのは仕組みを知らないと直感に反しているように感じるかもしれない。原理としてはファイルやフォルダーの書き込み可否は、あくまでその中身についての話なので、そのファイル・フォルダー自体を消せるかどうかは常に親フォルダーが握っているということ。

Sambaの設定をする際にも特定フォルダーはrootにオーナーシップを持たせておいて中のフォルダー構成を勝手にいじれないようにしつつ、その子フォルダーにSambaによる書き込み権限を与えるといったやり方で制御することがあるのでOSアクセス権の基本は抑えておきたい。

5. Linux Firewall

最近のLinuxではファイアウォールポートが必要最小限のポート意外は閉じているようで、個別にオープンさせる必要がある。
Sambaを使うには445ポートが空いていればOK。

[thom@storage ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eno1
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 445/tcp
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

6. Network Firewall

ここは大手企業ならNW担当の領域なので特にサーバー管理で躓く場所ではないし、自宅やワンマンIT担当なら自分で設定してるはずなので原因の一つになりえるということを念頭に置きさえすれば、特に改めて説明することはない。
自宅のNW-FWはCisco CBS250の簡易ACLでネットワーク間のトラフィックを制御しているのみで、ポート単位での細かい制御はしてないので特に引っかかることは無かった。

7. Windows Firewall

自分から始めた通信に対する戻りのトラフィックはデフォルトで許可されているはずなので、特に追加設定してなければ引っかかることはないはず。

どこが悪いのかの切り分け

初期設定でうまくいかないときはサーバーにデータが入る前なので一時的にSE LinuxやLinux Firewallをストップして通信がうまくいくか確かめてみる。一旦ごっそり設定を解除してまずは通信を成功させ、それから通信ができなくなるまで一つずつ有効にしていき原因を探る。原因が分かったらきちんと調べて適切な設定をすることが重要。使えるからまるっと無効のままでいいやっていうのはセキュリティ的に非常にまずい。

その他

実際はデータ保管機能だけじゃなくて一時ファイルの自動削除スクリプトとか、永久アーカイブ対象ファイルを暗号化してAWSのS3バケットに保管する機能だったりを作っている。

AWS連携は以前書いた記事があるので詳しくは割愛。
thom.hateblo.jp

暗号化の仕組み等は別途書いてる記事がある。
thom.hateblo.jp

フォルダー構成は色々と悩んだ結果こうなった。アーカイブの分類とかもう少し凝った構成で計画をXにポストしてたけど結局アーカイブ本来の目的を考えると保管じゃなくて保存だから旧サーバー同様に分類しない投げ込み式を踏襲。

アーカイブ・暗号化・AWS連携・一時ファイルの自動削除を実現する実際のbashスクリプトは以下をcronで1分毎に動かしている。

#!/bin/bash
FILES="/mnt/encrypted/ToArchive/*"
TIMESTAMP=`date +'%Y%m%d%H%M%S'`
PASSWORD="非公開情報のため削除"

#file existence check for source folder 
if [ -n "$(ls -A /mnt/encrypted/ToArchive/)" ];then
  for f in $FILES
  do
    #duplicated file existence check for destination folder 
    if [ ! -e /mnt/encrypted/Archive/$(basename -- $f) ]; then
      gzip -c $f | openssl enc -e -aes-256-cbc -pbkdf2 -iter 99999 -salt -k $PASSWORD -out /mnt/encrypted/sys_tmp/$(basename -- $f).gz.aes
      encf=/mnt/encrypted/sys_tmp/$(basename -- $f).gz.aes
      hfname=/mnt/encrypted/sys_tmp/`sha256sum -- $encf | awk '{print $1}'`.gz.aes
      mv $encf $hfname
      /usr/local/bin/aws s3 cp $hfname s3://非公開情報のため削除/ --profile 非公開情報のため削除
      mv $hfname /mnt/encrypted/ToBeArchivedInMedia/
      mv $f /mnt/encrypted/Archive/
      echo $TIMESTAMP $(basename -- $f) $(basename -- $hfname) >> /mnt/encrypted/Archive/Index.txt
    else
      if [ ! -d /mnt/encrypted/ArchiveError/$TIMESTAMP ]; then
        mkdir /mnt/encrypted/ArchiveError/$TIMESTAMP
      fi
      mv $f /mnt/encrypted/ArchiveError/$TIMESTAMP
    fi
  done
else
  :
fi

find /mnt/encrypted/Temp/10_minutes -type f -amin +10 -exec rm {} \;
find /mnt/encrypted/Temp/24_hours -type f -atime +1 -exec rm {} \;
find /mnt/encrypted/Temp/30_days -type f -atime +30 -exec rm {} \;

前回のサーバーとしてもうひとつ進化した点はファイル名の匿名化が挙げられる。

これによって万が一AWS S3やメディアバックアップが流出しても、中身はもちろんそのタイトルすら読めないので他人には内容の類推すらできないという安全なものになった。

機能刷新でハマったところ

まず久々に触るのでBashが読めない。特に$(basename -- $f)の部分が、調べ直した先の参考サイトと記載違っており、なんで前回「--」を書いたのか、何の意味があるのか全く分からずに半日を費やした。

答えはこちらにあった。
zenn.dev

Linuxのコマンドは「コマンド 複数のオプション 引数」という構成になってて、「--」はここでオプション終わりですよと明示する書き方らしい。それが無いと例えば今回のケースだと$fに入ってくるファイル名にスペースが入ってた場合、そこで区切った前半の内容がオプションと一致するとまずい。。。。そんなことあるか?まぁ一応ダブルダッシュはいれとこう。


次に現行機種で動いている暗号化スクリプトをそのまま採用すると警告が出るのでハマった。
オプションに-pbkdf2 -iter 99999を追加したらエラーは解決したんだけど、なんで旧サバで入れてないんだ?と思ったらOSが古くてOpen SSLのバージョンがそのオプションが登場する前のものしかリポジトリになかったのが原因だった。

新旧暗号化オプションが混じると復号化の方法が分かれてしまうため、今回は新オプションで過去のアーカイブも暗号化しなおしてAWSにアップロードしなおした。どのみちファイル名匿名化でアップロードし直したかったのでちょうどよかった。

最後にどうしても分からなかったのが、共有フォルダー配下のフォルダーの削除操作を拒否する方法。
次のような不可解な現象に悩まされて海外掲示板等も読み漁ったけど解決していない。

実用上は特に困ってないのでひとまずはそのまま運用することにした。

おわり

おわり。

家庭内のデータを消失リスク・流出リスクで分類して対策を考える

今回は以下記事の続きというよりは前提となっている話。
thom.hateblo.jp

自宅のsambaサーバーが老朽化してリプレースしているという話を書いたが、この気にデータ保管のポリシーをしっかり立てて管理しようと思って整理してみた。

これまではsambaサーバーに組み込んだ機能ありきで適当に運用していたんだけど、今回はきちんとデータのリスクを考えて整理してみた。

まずデータのリスクを消失と流出の2つの軸で考えてテーブルを作る。

イメージしやすくするために、自分が持っているデータの消失リスク・流出リスクを例示してみた。

※思い出の写真などは、被写体によって変わる。モノや風景なら流出リスクは小、自分なら中、友人や家族なら大といったところか。

そして、それぞれのマスに対してどういう対応をとると良いかをポリシーとして整理してみた。

このあたりは考え方や技術的にとりうる対応が人によっても違ってくるのでもしこれを参考に同じようなことを考えたい方は自分が実現可能な範囲ですると良いと思う。場合によっては印刷という選択肢もあるかもしれない。

そしてそのポリシーを満たすような実際の解決策を考えていく。

実は今わざわざNASじゃなくてファイルサーバーを構築している理由としてはデータの取り扱いをシンプルにするためである。
セキュリティと利便性は基本的にはトレードオフの関係になることが多いが、利便性を損ねずにセキュリティを高められる解決策があるのならセキュリティが必要ないデータにも高いセキュリティを適用してしまえば良い。

ということで私が考えた解決策がこちら。

このように全データに対し、自分がとりうる最高レベルのセキュリティを統一的に適用することで流出リスクを無視して消失リスクだけでデータの保管方法を決めることができる。

ということで、次回こそこれをsambaでどうやって実現しているのかを記事にしようと思う。
と言ってもまだ構築途中なのでもう少し先になるかなと思う。

Linuxで暗号化されたRAID10を構築したので概要を解説

今回はAlmaLinux OS 9で暗号化されたRAID10を構築してみた。
作成した暗号化ボリュームはSambaファイルサーバーの共有ファルダで使用する予定である。

※物理的なサーバーの組立は前回の記事を参照
thom.hateblo.jp

RAID(レイド)とは、複数のストレージ(HDD・SSD等)を組み合わせて使うことで速度アップしたり、故障時のデータの消失リスクを下げるためのテクノロジーである。

今回はLinuxのmdadmというツールでRAID10という仕組みを構築し、さらにそこに暗号化ボリュームを作って/mnt/encryptedにマウントし、そこにSambaの共有フォルダーを作成するという構成にした。保存領域の全体像はこんな感じ。

ごちゃごちゃしてよく分からないと言われてしまいそうなので順を追って説明する。

まずハードディスクを買ってSATAケーブルでマザーボードに接続すると、/dev/sdaのように認識される。
※複数のHDDを接続した場合はsdb、sdc…という風に続く。

そこにRAID用のパーティションを作成する。

これを複数セット用意してミラーリングさせたのがRAID 1と呼ばれる構成。

RAID 1の構成だとディスクを増やしてもバックアップに使われるので保存可能なデータ容量が増えないけど、ディスクの数だけバックアップがあるようなものなので、HDDが全滅しない限りはデータが消えないというメリットがある。

一方で、Raid 0という構成ではデータを切り分けて複数のディスクにそれぞれ別の部分を保存する。

HDDはアクセス速度が遅いけどRAID 0だと1つのデータに対して複数のHDDが分担して読み書きを行うのでその分アクセススピードが向上する。

そして、いま説明した2つの仕組みを組み合わせたのがRAID 10である。※1+0と表記されることもある。

今回は採用しなかったが、逆の組み合わせはRAID 01と表記される。※0+1と表記されることもある。図の都合で上から読みそうになるけど逆なので注意。

一見違いが分かりにくいかもしれないが、下図を見ていただくと対障害性でRAID10が勝っていることが分かる。

RAID 01の方はsdaが故障した時点で左側のRAID 0が機能しなくなるため、右側の2本で運用することになる。このうち1本が壊れたらシステムが完全停止となるので障害には弱い。
対してRAID 10はsdaが故障してもミラー先のsdbが生きているので左側のRAID 1はセーフ。この状態でsddが故障してもミラー先のsdcが生きているので右側のRAID 1もセーフ。よって全体を構成するRAID 0もセーフとなり、システム全体は正常に稼働を続ける。
まぁこの図だと4台しかないので、sdaとsdbが同時故障した場合は逆にRAID01の方がセーフということになるんだけど、台数が増えるとグループを跨いだ故障に強いRAID10に軍配が上がるという訳である。


RAIDには専用の基盤を用いるハードウェアRAIDとOS上のアプリケーションで実行するソフトウェアRAIDの2種類がある。
ハードウェアRAIDは専用基盤なのでCPUに負担がかからないけど高額、ソフトウェアRAIDは特に追加で購入する部品などは必要ないがCPUリソースを必要とするので一長一短である。

最初はハードウェアRAIDを考えていたけど、今回Amazonで比較的安価で販売されていたRAID10拡張カードのレビューコメントを見ると、これRAID 0+1だよって書かれているものがあったので気持ちが萎えた。RAID01のメリットは知らないので本当かどうかは分からない。ただどうやら調べてみると販売業者もRAID10とRAID01との区別がついておらず、どちらでも一緒だと考えてる人がいるようで、微妙なものをつかまされても困る。

今回はそもそも家庭で使うファイルサーバーなので、どのみちCPUリソースは持て余すことになる。ということで今回はLinuxのmdadmというツールを用いたソフトウェアRAIDを採用した。

作成したRAIDボリュームはmd0という名前を付け、/dev/md0というデバイス扱いになった。

この時点で同期処理が始まるので終わるまで待機し、完了したらLUKS(Linux Unified Key Setup)という仕組みでmd0を暗号化する。LUKSはディスク暗号化の仕様の名前なので、実際の暗号化にはcryptsetupsというツールを使用し、ボリューム名は参考にした記事に倣ってcryptdataとした。

このcryptdataボリュームにLinuxで一般的なext4形式のファイルシステムを構築しこれを/mnt配下に作成したencryptedフォルダにマウントする。マウントするときに暗号化キーを求められるが、これはキーファイルとして保存しておくことでOS起動時に自動マウントさせることができる。この仕組みだとOSが起動してしまえばデータは見えてしまうわけだけど、仮にディスク単体を抜き取られて盗み出されても他のPCからデータを見ることはできないので安全性は向上している。

さて、これでLinuxから/mnt/encryptedにアクセスすることで実際に暗号化されたRAID10領域を普通のファイルやフォルダを作成することができるスペースとして利用することができる。

ということで今回作成した暗号化RAIDの概要説明はここまで。

実際の手順は以下の2サイトを参考にほぼそのまま対応したのでここでの説明は割愛しようと思う。
ja.linux-console.net
e-penguiner.com

次回はここにSambaを構築する際に若干苦労した点や実装した独自機能について書こうと思う。

スリムPCケースとホットスワップ鍵付きHDDベイでプロフェッショナルな見た目のサーバー機を組み立てる

今回はIN WIN社のスリムPCケース IW-CE685/300P とStarTeck.comの簡易鍵付きHDDベイSATSASBP425を使ってなるべく業務用っぽい見た目のサーバー機を組み立ててみた。

ケースはこちら。

※同じ見た目のケースで型番違いも販売されているが、搭載電源の認定がBronzeかPlatinumかの違い。
通常サイズだとどうしてもクライアントPCっぽさが全開になってしまうので理想を言えばデータセンターにあるラックマウントサーバーが良いんだけど、個人での保守性を考えると無理があるのでなるべくスリムで飾り気がなく、横置きできるケースを選定した。

ケースの前面に装着するHDDドライブベイはこちら。

最初はホットスワップに対応したPCケースを見繕っていたんだけどシルバーストーン社くらいしか選択肢がなく、設置場所の都合で諦めた。
このHDDドライブベイは簡易的な鍵付き※で誤って開けてしまうこともなさそうなので完璧。
※付属の鍵でなくても、多分ラジオペンチ等の工具で突起部をつかんで強引に開けることは可能と思われる。破損しそうなのでやってない。指では無理だったのであくまで簡易ロック。

唯一気に入らない点はHDDのアクセスLEDが青色ということ。

そこは緑かオレンジにしてほしかった。青LEDはコンシューマー受けを狙った家電に多く使われていることもあって私が思い描くプロフェッショナルな見た目からは遠ざかる。なんか格好よく見せようとしてる感が鼻につくのだ。
まあでも、その他は理想的なので目をつむろう。見てるうちに慣れてきた気もするし。

サーバー機を新規調達する背景

2022年4月頃に導入した富士通のラックマウントサーバーだが最近フロントパネルの警告ランプが点滅するようになってしまった。
thom.hateblo.jp

修理しようにも機器が特殊すぎて診断のノウハウもないし、保守も切れてるので交換部品が分かったところでオークションの出品を待つことになる。
加えて、ようやく修理できたところで2024年6月には今使っているCentOS 7がサポート切れになり、他にこのハードでまともに動くOSは未確認。
ということで今回思い切って新規調達することにした。また同様のトラブルに備えてなるべく汎用部品で構成するというのが今回のミッションである。

その他の部品

マザーボードはこちらを調達。

コンシューマー向けの基盤は大半が黒に染まってしまった昨今、緑基盤のマザーボードは逆にレアになってしまった。ゲーミングPCでこれはないけど、サーバー用に使う分にはむしろ緑のほうが業務用っぽくて格好いい。Intel 12世代CPUに対応しつつ、緑基盤で今どき珍しいCOMポートが付いているってのが逆にすごい。
ちょっと最近保証問題で炎上騒ぎがあったのでどうかなというところではあったけど、まぁマザーボードメーカーは特定地域に偏ってるのでカスタマー対応にカルチャーがでてしまっているというのが正直な感想。だから本質的にはどこも似たり寄ったりだというのが現状の見立て。

それはいいとして2点気に入らない機能があって、キーボード未接続だと起動時に警告メッセージとビープが鳴ってしまうことと、モニター未接続だと電源LEDがずっと点滅しっぱなしになることだ。キーボード警告はネットで調べながらBIOS上でOFFにする方法を探したけど見つからず、モニター警告のOFFはその他重要な機能のチェックと共通になっているのでOFFにすると故障診断が心配。あくまでパソコン用のメインボードなのでサーバーとしての使われ方は想定されていない。それがネックになった。

仕方がないのでとりあえずVGAダミーを調達して到着待ち。

HDMIダミーのほうがコンパクトだけどなぜか販売品はツヤっとしてて形状も丸みを帯びていかにもコンシューマー向けっぽいので避けた。
そこ、なんでターゲティングミスるかな。そんなマニアチックな商品求める層なんて、飾り気のない業務用志向が強いに決まってるのに。

CPUはCeleron。

Intel 12世代の最弱CPUだがそれだけに消費電力の低さはピカイチ。今回はそんなに計算リソースを使わないけど24h x 365d稼働のファイルサーバー用途なので発熱しにくい点も魅力的。ただ需要が限定的なためか全然流通してないようで価格は高騰しており、同世代のCore i3よりも高い値段での調達となってしまった。

メモリ・SSDはCrucial

メモリやSSDは聞いたことないような企業が沢山あって迷いがち。Crucialはアメリカの大手半導体会社マイクロンが擁するブランドで、値段はピンキリだけど廉価品でも品質に定評があるので迷ったらCrucialでいいと思う。

そしてフロントのHDDベイに付けるのがウエスタンデジタルのBlue。

Raid10を組むため、4本購入した。

本当はWD Red NAS 2.5インチが欲しかったんだけど、Amazonでは在庫切れで再販の目途も不明。HDDは大容量化に柁をきっているせいか2.5インチはSSDが主流で、2.5インチHDDはだんだんと選択肢が限られてきているように感じる。

部品は以上。

組立て

作業に夢中でそんなに写真は取ってなかったけど、マザーボードにM.2 SSD、CPU、リテールクーラー、メモリの順で搭載してケースへ入れて固定したところ。

全体的に緑と黒。ひと昔前はこれをダサイと感じてたんだけど逆にレアになってしまって一周まわってこの飾り気のなさが格好よく見えてくる。

フロントパネルのIOケーブルの取り付けに当たってはLEDの極性が分からなかった※ので念のためテスターのダイオードモードで確認するなど、電子工作の知識が活きる場面もあった。

※まぁケーブルの色通りだろとは思っていて結論その通りだったんだけど、ボードに挿すとLEDと書かれた印字が見えない向きになってしまうのでまさかと思って念のため確認した。

あとケースのフロントパネルケーブルはどんなマザーボードにも適合できるようにバラバラになってるのでそれぞれマザーボードに挿していく作業がすごくイライラする。効率の意味では本末転倒ではあるが、更に面倒くさい中間ケーブルの自作をすることで満足のいく組立になった。

電子工作でおなじみのデュポン端子なので道具やカラーケーブルは一通りそろってる。

極性が無い電源スイッチ・リセットスイッチは同色ケーブル2本で、極性がある電源LED・HDD-LEDはマイナスを白で元のケーブルと合わせた。

満足。あとはマザーボードに挿すだけ。

ただまぁどれだけ綺麗に収めようとしても、裏配線の無いケースではこれくらいが限界だった。

サーバー機の用途

今回組み立てたサーバー機にはAlmaLinux OS 9 を入れてSambaサーバーを動かしている。自宅で使うのにNASではなくあえてファイルサーバーにした理由として、私は多少プログラムが書けるのでLinuxサーバーにしておくことで独自機能を実装できるためだ。

従来サーバーで実装していたのがこちら。

  • 書きこんだデータを自動的に読み取り専用のフォルダーに移動させる簡易WORM(Write Once Read Many)機能
  • ファイルを暗号化してAmazon S3バケットに保管するアーカイブ機能

加えて、今回新たに実装したのがこちら。

  • 一定時間で自動削除されるTempフォルダー
  • ディスクレベルでの暗号化

これはこのあとまた別の記事で紹介したいと思う。

ということで今回はここまで。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。