見た目が綺麗で動作も軽快な「nextExplorer」

ファイルサーバーとしても利用可能なツールとして、「OxiCloud」や「Filebrowser」を紹介しましたが、見た目が綺麗で、ファイルやフォルダの共有も行いやすい「nextExplorer」も使いやすそうです。
実際の使用画面は次のような感じで、動作も軽快。GitHubで公開されており、セルフホストが可能です。

LXDコンテナ内にDockerでセットアップ

#!/usr/bin/env bash
# =============================================================================
#  nextExplorer セットアップスクリプト v3
#  - /opt/nextexplorer に docker-compose.yml を配置
#  - コンテナ内ポート 3000 → ホスト 127.0.0.1:3317 にバインド
#  - Tailscale Serve で https://<hostname>:3317 → :3317 に追加(ポートベース)
#  - 既存の Serve 設定は壊さない(--bg)
#  - データディレクトリのパーミッションを正しく設定
# =============================================================================
set -euo pipefail

# ── 設定 ──────────────────────────────────────────────────────────────────────
INSTALL_DIR="/opt/nextexplorer"
HOST_PORT=3317
CONTAINER_PORT=3000
DATA_DIR="/srv/nextexplorer"   # config / cache / files の実体

# コンテナ内プロセスの実行ユーザーに合わせる
# nxzai/explorer は内部で node ユーザー(uid=1000) を使用
PUID=$(id -u)
PGID=$(id -g)

# ── 色付きログ ─────────────────────────────────────────────────────────────────
info()  { echo -e "\033[1;34m[INFO]\033[0m  $*"; }
ok()    { echo -e "\033[1;32m[ OK ]\033[0m  $*"; }
warn()  { echo -e "\033[1;33m[WARN]\033[0m  $*"; }
die()   { echo -e "\033[1;31m[ERR ]\033[0m  $*" >&2; exit 1; }

# ── 前提チェック ───────────────────────────────────────────────────────────────
info "前提確認..."
command -v docker        >/dev/null 2>&1 || die "docker が見つかりません"
docker compose version   >/dev/null 2>&1 || die "docker compose (v2) が見つかりません"
command -v tailscale     >/dev/null 2>&1 || die "tailscale が見つかりません"
tailscale status         >/dev/null 2>&1 || die "Tailscale が認証されていません"
ok "前提 OK"

# ── Tailscale hostname 取得 ────────────────────────────────────────────────────
TS_HOSTNAME=$(tailscale status --json \
  | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['Self']['DNSName'].rstrip('.'))" \
  2>/dev/null) || die "Tailscale の DNSName を取得できませんでした"

PUBLIC_URL="https://${TS_HOSTNAME}:${HOST_PORT}"
info "Tailscale ホスト : ${TS_HOSTNAME}"
info "PUBLIC_URL       : ${PUBLIC_URL}"

# ── ディレクトリ作成 & パーミッション設定 ─────────────────────────────────────
info "ディレクトリ作成..."
mkdir -p "${INSTALL_DIR}"
mkdir -p "${DATA_DIR}/config"
mkdir -p "${DATA_DIR}/cache"
mkdir -p "${DATA_DIR}/files"

# コンテナ内 node(1000) / コンテナ外の実行ユーザー 両方が書けるように
# ホスト uid と合わせるか、777 で開放するかを選択
# → ここでは実行ユーザー所有 + グループ書き込み可 にする
chown -R "${PUID}:${PGID}" "${DATA_DIR}"
chmod -R u=rwX,g=rwX,o=rX "${DATA_DIR}"
# コンテナが uid=1000 で動く場合に備えて ACL を追加(acl パッケージがある場合のみ)
if command -v setfacl >/dev/null 2>&1; then
  setfacl -R -m u:1000:rwX "${DATA_DIR}"
  setfacl -R -d -m u:1000:rwX "${DATA_DIR}"
  info "ACL: uid=1000 に rwX を付与しました"
else
  # ACL が使えない場合は o+w を付与してコンテナ書き込みを許可
  chmod -R o+w "${DATA_DIR}/config" "${DATA_DIR}/cache" "${DATA_DIR}/files"
  warn "acl パッケージが未インストールのため chmod o+w で代替しました"
  warn "  sudo apt install acl で改善できます"
fi
ok "ディレクトリ & パーミッション設定完了"

# ── SESSION_SECRET 生成(既存ファイルがあれば再利用) ─────────────────────────
SECRET_FILE="${INSTALL_DIR}/.session_secret"
if [[ -f "${SECRET_FILE}" ]]; then
  SESSION_SECRET=$(cat "${SECRET_FILE}")
  info "既存の SESSION_SECRET を再利用します"
else
  SESSION_SECRET=$(python3 -c "import secrets; print(secrets.token_hex(32))")
  echo "${SESSION_SECRET}" > "${SECRET_FILE}"
  chmod 600 "${SECRET_FILE}"
  info "SESSION_SECRET を新規生成しました"
fi

# ── docker-compose.yml 生成 ───────────────────────────────────────────────────
info "docker-compose.yml を生成..."
cat > "${INSTALL_DIR}/docker-compose.yml" <<EOF
# nextExplorer — docker-compose.yml
# 生成日: $(date '+%Y-%m-%d %H:%M:%S')
# アクセス URL: ${PUBLIC_URL}

services:
  nextexplorer:
    image: nxzai/explorer:latest
    container_name: nextexplorer
    restart: unless-stopped
    ports:
      # ループバックのみ。Tailscale Serve 経由でのみアクセス可能
      - "127.0.0.1:${HOST_PORT}:${CONTAINER_PORT}"
    environment:
      NODE_ENV: production
      PORT: "${CONTAINER_PORT}"
      # ポートベースの URL(サブパスなし)
      PUBLIC_URL: "${PUBLIC_URL}"
      # Tailscale Serve (loopback) を信頼
      TRUST_PROXY: "loopback"
      # 再起動をまたいでセッションを維持
      SESSION_SECRET: "${SESSION_SECRET}"
      # コンテナ内プロセスの UID/GID をホストに合わせる → 書き込み権限の解決
      PUID: "${PUID}"
      PGID: "${PGID}"
    volumes:
      - ${DATA_DIR}/config:/config
      - ${DATA_DIR}/cache:/cache
      # /mnt/<ラベル名> が UI 上のボリュームになる。必要に応じて追加
      - ${DATA_DIR}/files:/mnt/Files
EOF
ok "docker-compose.yml → ${INSTALL_DIR}/docker-compose.yml"

# ── コンテナ起動 ──────────────────────────────────────────────────────────────
info "コンテナを起動..."
docker compose -f "${INSTALL_DIR}/docker-compose.yml" pull
docker compose -f "${INSTALL_DIR}/docker-compose.yml" up -d
ok "コンテナ起動完了"

# ── Tailscale Serve 設定(ポートベース) ──────────────────────────────────────
info "既存の Tailscale Serve 設定を確認..."
EXISTING_SERVE=$(tailscale serve status 2>/dev/null || true)

if echo "${EXISTING_SERVE}" | grep -q ":${HOST_PORT}"; then
  warn "ポート ${HOST_PORT} はすでに Tailscale Serve に登録されています。スキップします。"
else
  info "Tailscale Serve にポート ${HOST_PORT} の HTTPS プロキシを追加..."
  # --bg        : バックグラウンドモード(既存設定を保持したまま追加)
  # --https=N   : Tailnet 内で HTTPS ポート N として公開
  tailscale serve --bg --https="${HOST_PORT}" "http://127.0.0.1:${HOST_PORT}"
  ok "Tailscale Serve 設定追加完了"
fi

# ── 完了サマリー ──────────────────────────────────────────────────────────────
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
ok "セットアップ完了!"
echo ""
echo "  アクセス URL  : ${PUBLIC_URL}"
echo "  設定ファイル  : ${INSTALL_DIR}/docker-compose.yml"
echo "  データ領域    : ${DATA_DIR}/"
echo "    ├─ config/  (DB・設定)"
echo "    ├─ cache/   (サムネイルキャッシュ)"
echo "    └─ files/   (公開ファイル置き場 → UI上: Files)"
echo ""
echo "  ボリュームを追加したい場合:"
echo "    ${INSTALL_DIR}/docker-compose.yml の volumes に"
echo "    - /your/path:/mnt/LabelName  を追記して"
echo "    docker compose -f ${INSTALL_DIR}/docker-compose.yml up -d"
echo ""
echo "  現在の Tailscale Serve 設定:"
tailscale serve status
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

インストールが完了してアクセスすれば次のような画面が表示されるので、メールアドレスやパスワードを設定してログインします。

Locationsにフォルダを追加する方法

docker-compose.yml の volumes セクションにマウントを追加するだけです。

volumes:
  - /srv/nextexplorer/config:/config
  - /srv/nextexplorer/cache:/cache
  - /srv/nextexplorer/files:/mnt/Files   # 既存
  - /home/user/photos:/mnt/Photos        # 追加例
  - /mnt/nas/documents:/mnt/Documents    # 追加例

/mnt/ 以降の名前(PhotosDocuments など)がそのまま UI 上のラベルになります。

編集と反映するコマンド

# 編集
nano /opt/nextexplorer/docker-compose.yml
# 編集後
docker compose -f /opt/nextexplorer/docker-compose.yml up -d

デフォルトの Files フォルダを別パスに変えたい場合も同じで、既存の行のホスト側パスを書き換えるだけです。

# 変更前
- /srv/nextexplorer/files:/mnt/Files

# 変更後(例:/data/storage を Files として公開)
- /opt/lxd-data:/mnt/Files

注意点として、追加したディレクトリにコンテナ(uid=1000)が書き込む必要がある場合は、スクリプトで設定したのと同じようにパーミッションを合わせてください。

# acl が入っている場合
sudo setfacl -R -m u:1000:rwX /your/path
sudo setfacl -R -d -m u:1000:rwX /your/path

# acl なしの場合
sudo chmod -R o+w /your/path
タイトルとURLをコピーしました