🦑

ミニPCでマルチサーバー構築 [Sambaコンテナ]

2024/05/17に公開


ミニPCでマルチサーバー構築シリーズのSambaコンテナ構築の記録メモです。以前構築した際も色々大変だった記憶がありますが、今回も大変でした。

シリーズ

  1. N100搭載ミニPCでマルチサーバーの構想と構築準備
  2. ミニPCでマルチサーバー構築 [OS等インストール]
  3. ミニPCでマルチサーバー構築 [Sambaコンテナ] この記事
  4. ミニPCでマルチサーバー構築 [PostgreSQLコンテナ]
  5. ミニPCでマルチサーバー構築 [Nginxコンテナ]
  6. ミニPCでマルチサーバー構築 [Immichコンテナ]
  7. ミニPCでマルチサーバー構築 [VaultwardenコンテナとTailscale]
  8. ミニPCでマルチサーバー構築 [AdGuard Homeコンテナ]
  9. ミニPCでマルチサーバー構築 [GUI環境整備]

簡単な要件

  • 共有サーバーへはIPアドレスを指定してアクセスする
  • Port445でのみ通信する (NetBIOS等使用しない)
  • 指定ディレクトリのファイル共有機能のみ使用する
  • 共有ディレクトリにアクセスする際は毎初回ログインする
  • ユーザー管理はSambaで独立して行う
    • 暗号化パスワードを使用する
  • ゲストログインは一切許可しない
  • usersグループのユーザのみアクセス可能にする
  • 読み書き可能にする
  • 共有単位内でのシンボリックリンクを辿るのは許可する
  • ゴミ箱機能は使用しない

コンテナ化

検討事項

  • Samba公式のDocker imageは存在しない
    • 現時点で最近もメンテナンスされている野良イメージは存在する
      • ただし個人運営のようで、いつメンテ停止するか不明
      • メンテナンスが停止した実績1,実績2, 等
  • 野良イメージはゴミ箱機能など不要な機能が含まれる
    • 意識しなくていいとはいえ不要な機能は極力入れたくない
  • そのためOSイメージから自分で構築することにした
    • alpineが好ましいが不慣れなため不採用
    • 意外にも現時点で容量がより少ないubuntu:latestを採用
      • ubuntu:latest 27.53MB (d21429c46353 linux/amd64)
      • debian:stable-slim 27.8MB (04a4090043d8 linux/amd64)

Dockerfile

Dockerfileではタイムゾーン設定とSambaインストールのみ実施。

Dockerfile
FROM ubuntu:latest
ARG DEBIAN_FRONTEND=noninteractive
RUN echo Asia/Tokyo > /etc/timezone \
    && apt update && apt install -y samba \
    && rm -rf /var/lib/apt/lists/*

Docker Compose周り作成

ディレクトリ構成

$ tree .
.
├── compose.yaml
└── samba
    ├── Dockerfile
    ├── etc
    │   └── smb.conf
    ├── run
    │   ├── dfree_main.sh
    │   └── entrypoint.sh
    └── secrets
        └── credential

compose.yaml

compose.yaml
services:
  samba:
    build:
      context: ./samba
      dockerfile: Dockerfile
    init: true
    restart: unless-stopped
    ports:
      - "445:445"
    configs:
      - source: common-user
        target: /etc/passwd-
      - source: common-group
        target: /etc/group-
      - source: samba-entrypoint
        target: /run/bin
    secrets:
      - source: samba-secrets
        target: /run/secrets
    volumes:
      - /mnt/ssd1:/srv/samba/main/ssd1
      - ./samba/etc:/etc/samba
      - /var/log/samba:/var/log/samba
    networks:
      - smbnet
    command: /bin/sh -c "/run/bin/entrypoint.sh"

configs:
  common-user:
    file: /etc/passwd
  common-group:
    file: /etc/group
  samba-entrypoint:
    file: ./samba/run

secrets:
  samba-secrets:
    file: ./samba/secrets

networks:
  smbnet:

Entrypoint

entrypoint.sh
#!/bin/sh
cat /etc/passwd- > /etc/passwd
cat /etc/group- > /etc/group

credential_ro=/run/secrets/credential
credential_rw=/run/credential
cp $credential_ro $credential_rw
pdbedit -i smbpasswd:$credential_rw

smbd --foreground --no-process-group

設定

実際の設定ファイル

smb.conf
[global]
   workgroup = WORKGROUP
   server string = %h
   log file = /var/log/samba/%J.log
   max log size = 1000
   logging = file
   panic action = /usr/share/samba/panic-action %d
   server role = standalone server
   obey pam restrictions = no
   unix password sync = no
   pam password change = yes
   map to guest = never
   usershare allow guests = no

   disable netbios = yes
   disable spoolss = yes

   guest ok = no
   follow symlinks = yes
   writable = yes
   create mask = 0664
   force create mode = 0664
   directory mask = 0775
   force directory mode = 0775
   force group = users
   valid users = @users
   printable = no
   load printers = no
   printing = bsd
   printcap name = /dev/null

[printers]
   comment = All Printers
   browseable = no
   path = /var/tmp
   printable = yes
   read only = yes
   create mask = 0700

[main]
   path = /srv/samba/main
   dfree command = /run/bin/dfree_main.sh
[sub]
   path = /srv/samba/sub
   dfree command = /run/bin/dfree_sub.sh
   valid users = admin

globalセクション

記載するglobalセクション項目

  • workgroup: 同グループのWindowsからアクセス可能にする
  • log file: 445ポートのみの場合は%mが使用不可のため%Jに変更
  • server role: standaloneを設定し次を有効にする
    • ログイン要求
    • 暗号化パスワードの使用
  • obey pam restrictions: 暗号化パスワードを使用するためno
  • unix password sync: ユーザー設定を別管理にするためno
  • pam password change: パスワード変更にPAMを使用するためyes
  • map to guest: ゲストログインは許可しないためnever
  • usershare allow guests: ゲストログインは許可しないためno
  • disable netbios: NetBIOSを使用しないためyes
  • disable spoolss: プリンタ共有を使用しないためyes

記載する各セクション向け項目

  • guest ok: ゲストログインは許可しないためno
  • follow symlinks: 共有単位内でのリンクは許可するためyes
  • writable: 読み書き可能にするためyes
  • create mask: ファイルの権限固定のため0664
  • force create mode: ファイルの権限固定のため0664
  • directory mask: ディレクトリの権限固定のため0775
  • force directory mode: ディレクトリの権限固定のため0775
  • force group: usersはアクセス可能とするためusers
  • valid users: users所属ユーザは有効とするため@users
  • printable: プリンタ共有を使用しないためno
  • load printers: エラーログ抑制のためno
  • printing: CUPサーバーの存在確認抑制のためbsd
    • デフォルト動作ではCUPSサーバーを確認し都度エラーログ発生
  • printcap name: エラーログ抑制のため/dev/null
    • bsdだとCUPSサーバーの代わりに/etc/printcapを確認する
    • /etc/printcapが存在しないと都度エラーログ発生のため変更

記載しなかったデフォルト項目

  • passwd program: unix password syncnoにするため削除
  • passwd chat: unix password syncnoにするため削除

printersセクション

  • printable: yesでなければ設定ファイルが有効にならないためyes
  • プリンタ共有は使用しないため、それ以外はデフォルトまま

共有ディレクトリセクション

  • dfree command: 空き容量確認スクリプトのパスを指定
    • Sambaは以下の場合に空き容量が正確に取得できない
      • path以下に別途パーティションをマウントしている場合
    • それらを正しく認識するためのスクリプトを準備する必要がある
      • 参考サイト
      • dfを用いたサンプルスクリプト
        sample script
        #!/bin/bash
        target=/srv/samba/share
        total=0
        avail=0
        while read line; do
           ary=($line)
           total=$(($total+${ary[0]}))
           avail=$(($avail+${ary[1]}))
        done < <(df -k --output=size,avail,target | grep $target)
        echo $total $avail
        
    • 現在公式サイトには以下のように書いてある

      should be owned by (and writeable only by) root!

      • しかし所有者がrootではなぜか動作しなかった
        • 所有者をユーザーにすると動作した
      • 相当ハマったため動作しなくなる可能性のある事を公式が推奨するのは本当に勘弁してほしい

Sambaのユーザー管理注意点

Sambaのユーザー

  • Linux上にユーザーが存在しなければならない
  • /etc/passwd,/etc/groupは読み書き可能でなければならない

Sambaのパスワード設定

Docker Composeで扱う際にパスワードを平文で管理したくないため、暗号化されたハッシュ状態のパスワードを取り扱うようにする。

  • ハッシュ状態のパスワードで取り扱う方法
    1. 予めSandbox環境のSambaでユーザを作成する
      • UIDやGIDは同じ環境でなければならない
    2. 以下コマンドでハッシュ状態のパスワード等をエクスポートする
      • pdbedit -L -w > ./credential
    3. 以下コマンドでProduction環境でインポートする
      • pdbedit -i smbpasswd:./credential
      • ただし./credentialは読み書き可能でなければならない
  • パスワード等を取り出す際、pdbedit -eを使用してはならない
    • UID等が正しくない状態でエクスポートされる
      • 実際にそうであることを確認した
    • 公式ではpdbedit -eで移行を容易にできると書いている

      This option will ease migration from one passdb backend to another and will ease backing up.

    • 相当ハマったため本当に勘弁してほしい

所感

今回改めてSambaを設定しましたが、個人のファイル共有でSambaを使うのは複雑すぎて面倒すぎると感じました。Windows側もエクスプローラが勝手に認証情報をキャッシュのような事をしたりして想定外の動きになったり無駄にややこしいです。小規模環境でのWindowsとの共有であれば、WindowsのWSL2上にnfsを使って共有した方がいい気がしました。エクスプローラから\\wsl$にアクセスすればLinuxにアクセスしてる感もありません。問題が出るとすればファイル所有者,権限周りぐらいでしょうか? Windows以外のスマホ等との共有も必要であればWebDAV経由にする等必要ですが、Sambaを使うよりは疲弊が少ない気がします。

参考文献

Discussion