32blogby StudioMitsu

chmod・chown実践ガイド:権限トラブルを即解決

chmodとchownでLinuxのファイル権限と所有者を操る方法を実例で解説。数値・シンボル指定、再帰変更、setuid/setgid、スティッキービット、umask、実務パターン集。

21 min read
目次

chmod はファイルに対して「何ができるか」を設定する。chown は「誰のものか」を設定する。この2つがLinuxのパーミッションモデルの全て——所有者で身元を、権限で行動範囲を決める。

要は chmod 755 script.sh で所有者にフルアクセス、それ以外に読み取り+実行を付与。chown deploy:www-data /var/www で所有者とグループを変更。-R で再帰的に適用。umask で新規ファイルのデフォルト権限を制御。

Linuxパーミッションの仕組み

Linuxのファイルとディレクトリには、3つのメタデータがある:

  1. 所有者(Owner) — ファイルを所有するユーザー
  2. グループ(Group) — ファイルに紐づくグループ
  3. パーミッション(Permissions) — 各カテゴリ(所有者・グループ・その他)が何をできるか

ls -l で全部見える:

bash
ls -l deploy.sh
# -rwxr-xr-- 1 furuya developers 2048 Mar 23 10:00 deploy.sh

-rwxr-xr-- の読み方:

位置文字意味
1-ファイルタイプ(- = ファイル、d = ディレクトリ、l = シンボリックリンク)
2-4rwx所有者の権限(読み取り、書き込み、実行)
5-7r-xグループの権限(読み取り、実行)
8-10r--その他の権限(読み取りのみ)

furuya が所有者、developers がグループ。developers グループに属するユーザーはグループ権限が適用される。それ以外のユーザーは「その他」の権限になる。

Permission deniedが出る理由

サーバーで一番よく見るエラー:

bash
bash: ./deploy.sh: Permission denied

原因はだいたい3つ:

  1. 実行ビットが設定されていない(chmod +x deploy.sh で解決)
  2. 所有者じゃなくて、グループ・その他に権限がない
  3. 親ディレクトリのトラバース権限がない(パス上のディレクトリに x がない)

32blogのステージングサーバーで、Nginxが静的ファイルを配信できない問題に20分ハマったことがある。ファイルは 644(正しい)だったけど、/var/www/32blog ディレクトリが 700 だった。Nginxの www-data ユーザーがディレクトリに入れなかった。755 に変えたら一発で動いた。

chmod: 数値とシンボルで権限を設定する

chmodには2つの書き方がある。好みで使い分ければいい——やってることは全く同じ。

数値(8進数)モード

権限を数値に対応させる: 読み取り = 4、書き込み = 2、実行 = 1。カテゴリごとに足し算。

数値2進数権限意味
7111rwxフルアクセス
6110rw-読み取り + 書き込み
5101r-x読み取り + 実行
4100r--読み取りのみ
0000---アクセス不可
bash
# 所有者: rwx、グループ: r-x、その他: r-x
chmod 755 deploy.sh

# 所有者: rw-、グループ: r--、その他: r--
chmod 644 config.yaml

# 所有者: rwx、グループ: ---、その他: ---
chmod 700 ~/.ssh

# 所有者: rw-、グループ: rw-、その他: ---
chmod 660 shared-log.txt

シンボリックモード

数値の代わりに文字を使う。書式は [対象][演算子][権限]:

  • 対象: u(所有者)、g(グループ)、o(その他)、a(全員)
  • 演算子: +(追加)、-(削除)、=(完全に設定)
  • 権限: r(読み取り)、w(書き込み)、x(実行)
bash
# 全員に実行権限を追加
chmod a+x deploy.sh

# グループとその他から書き込み権限を削除
chmod go-w config.yaml

# 所有者にフルアクセス、それ以外に読み取り+実行を設定
chmod u=rwx,go=rx deploy.sh    # chmod 755 と同じ

# グループだけに書き込み権限を追加
chmod g+w shared-project/

シンボリックモードは「一箇所だけ変えたい」ときに強い。chmod g+w file はグループの書き込み権限だけ追加して、他は一切触らない。数値モードだと現在の権限を先に確認する必要がある。

-R で再帰的に変更

bash
# ディレクトリを755、ファイルを644に設定 — Webサーバーの標準
chmod -R 755 /var/www/32blog/

# でもこれだとファイルまで実行可能になる。正しい方法:
find /var/www/32blog -type d -exec chmod 755 {} +
find /var/www/32blog -type f -exec chmod 644 {} +

よく使うchmodパターン

bash
# スクリプトを実行可能にする
chmod +x scripts/deploy.sh

# SSH鍵を保護(権限が緩いとSSHが鍵を拒否する)
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 700 ~/.ssh

# Webアプリのファイル
find /var/www/app -type d -exec chmod 755 {} +
find /var/www/app -type f -exec chmod 644 {} +

# グループメンバーが書き込める共有ディレクトリ
chmod 775 /opt/shared-project/

# その他のアクセスを完全に遮断
chmod o= sensitive-data/

chown: ファイルの所有者を変更する

chown はファイルの所有者とグループを変更する。chmod と違って、chown は基本的に sudo が必要——自分のファイルを他人に渡すにはroot権限がいる。

基本構文

bash
# 所有者だけ変更
sudo chown deploy deploy.sh

# 所有者とグループを同時に変更
sudo chown deploy:www-data /var/www/32blog/

# グループだけ変更(コロンの前を省略)
sudo chown :www-data /var/www/32blog/index.html

# chgrpでも同じことができる
sudo chgrp www-data /var/www/32blog/index.html

user:group の書式で一番よくあるケースを1コマンドで処理できる。32blogの新しいデプロイ環境を作るとき、最初に叩くのがこれ:

bash
sudo chown -R deploy:www-data /var/www/32blog

deploy ユーザーに所有権を渡して(デプロイスクリプトがファイルを書ける)、www-data グループにアクセスを与える(Nginxが読める)。

再帰的に所有者を変更

bash
# ディレクトリツリー全体の所有者とグループを変更
sudo chown -R deploy:www-data /var/www/32blog/

# グループだけ再帰的に変更
sudo chown -R :developers /opt/project/

# 変更内容を表示(verboseモード)
sudo chown -Rv deploy:www-data /var/www/32blog/

別のファイルから所有権をコピー

bash
# reference.conf と同じ所有者・グループに合わせる
sudo chown --reference=reference.conf target.conf

既存の設定ファイルに合わせて新しいファイルの権限を揃えるときに便利。

シンボリックリンクの扱い

デフォルトでは chown はシンボリックリンクをたどってリンク先のファイルを変更する。-h でリンク自体を変更:

bash
# リンク先の所有者が変わる
sudo chown deploy:www-data /var/www/current

# シンボリックリンク自体の所有者が変わる
sudo chown -h deploy:www-data /var/www/current

特殊パーミッション: setuid, setgid, スティッキービット

基本のrwx以外に、Linuxには3つの特殊パーミッションビットがある。セキュリティ監査で必ず確認する項目。

setuid(Set User ID)

実行ファイルに設定すると、実行したユーザーではなく ファイルの所有者 の権限で動作する。代表例:

bash
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 Mar 23 10:00 /usr/bin/passwd

所有者の実行権限が s になっている。passwd は一般ユーザーが実行してもroot権限で動く——/etc/shadow への書き込みが必要だから。chmodのmanページにこれらの特殊ビットの詳細がある。

bash
# setuidビットを設定
chmod u+s /usr/local/bin/my-tool

# 数値指定(先頭に4をつける)
chmod 4755 /usr/local/bin/my-tool

# setuidを削除
chmod u-s /usr/local/bin/my-tool

setgid(Set Group ID)

実行ファイルではsetuidのグループ版。でもよく使うのは ディレクトリ に対して——中で作られたファイルがディレクトリのグループを継承する:

bash
# 共有プロジェクトディレクトリを作成
sudo mkdir /opt/team-project
sudo chown :developers /opt/team-project
sudo chmod 2775 /opt/team-project

# 中で作ったファイルは自動的に developers グループになる
touch /opt/team-project/notes.txt
ls -l /opt/team-project/notes.txt
# -rw-rw-r-- 1 furuya developers 0 Mar 23 10:00 notes.txt

setgidがないと、作成したユーザーのプライマリグループが付くので共有アクセスが壊れる。

bash
# ディレクトリのsetgidを確認
ls -ld /opt/team-project
# drwxrwsr-x 2 root developers 4096 Mar 23 10:00 /opt/team-project
#      ^ この 's' がsetgid

スティッキービット

ディレクトリに書き込み権限があっても、他人のファイルを削除できなくする。/tmp が典型例:

bash
ls -ld /tmp
# drwxrwxrwt 15 root root 4096 Mar 23 10:00 /tmp
#          ^ この 't' がスティッキービット

/tmp には全員が書き込めるけど、自分のファイルしか消せない。

bash
# スティッキービットを設定
chmod +t /opt/shared-uploads/

# 数値指定(先頭に1をつける)
chmod 1777 /tmp

# スティッキービットを削除
chmod -t /opt/shared-uploads/

早見表

ビット数値(先頭)シンボルファイルへの効果ディレクトリへの効果
setuid4u+s所有者権限で実行(効果なし)
setgid2g+sグループ権限で実行新規ファイルがグループを継承
sticky1+t(効果なし)自分のファイルしか削除不可

特殊パーミッションのファイルを探す

セキュリティ監査でsetuid/setgidバイナリの洗い出しはよくある:

bash
# setuidファイルを全検索
find / -perm -4000 -type f 2>/dev/null

# setgidファイルを全検索
find / -perm -2000 -type f 2>/dev/null

# 両方
find / -perm /6000 -type f 2>/dev/null

32blogのインフラサーバーを構築するたびにこれを実行している。想定外のsetuidバイナリがあったら危険信号。

umask: デフォルトの権限を制御する

ファイルやディレクトリを作るたびに、システムは umask を適用する。umaskはデフォルトから権限を引き算するマスクで、ファイルのデフォルトは 666、ディレクトリのデフォルトは 777

bash
# 現在のumaskを確認
umask
# 0022

# シンボリック形式で確認
umask -S
# u=rwx,g=rx,o=rx

umaskの計算方法

umaskはデフォルトから権限を 差し引く:

デフォルトumask 022結果
ファイル666 (rw-rw-rw-)022644 (rw-r--r--)
ディレクトリ777 (rwxrwxrwx)022755 (rwxr-xr-x)

よく使うumask値:

umaskファイルディレクトリ用途
022644755大半のシステムのデフォルト
002664775グループ共有開発環境
077600700最大限のプライバシー
027640750バランス型セキュリティ
bash
# 現在のセッションのumaskを設定
umask 027

# テスト
touch test-file
mkdir test-dir
ls -l test-file    # -rw-r----- (640)
ls -ld test-dir    # drwxr-x--- (750)

umaskを永続化する

umaskは新しいシェルセッションのたびにリセットされる。永続化するにはシェルプロファイルに追記:

bash
# bashの場合
echo "umask 027" >> ~/.bashrc

# zshの場合
echo "umask 027" >> ~/.zshrc

# システム全体(全ユーザー)
echo "umask 027" >> /etc/profile

システムサービスの場合、シェルプロファイルのumaskは効かない。systemdのユニットファイルで [Service] セクションに UMask=027 を書く。

実務で使うパーミッション設定パターン

実際にプロダクションサーバーと開発環境で使っているパターン集。

Webサーバー構成(Nginx + デプロイユーザー)

bash
# Webルートを作成
sudo mkdir -p /var/www/32blog
sudo chown -R deploy:www-data /var/www/32blog

# 権限を設定
find /var/www/32blog -type d -exec chmod 2755 {} +
find /var/www/32blog -type f -exec chmod 644 {} +

# アプリが書き込む必要があるディレクトリ(アップロード、キャッシュ)
chmod 2775 /var/www/32blog/.next/cache

ディレクトリの 2755 はsetgidビット付き。deployプロセスが作ったファイルが自動的に www-data グループを継承するので、Nginxが必ず読める。

SSH鍵の権限

SSHは権限に厳格で、緩いと鍵の使用を拒否する:

bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519         # 秘密鍵
chmod 644 ~/.ssh/id_ed25519.pub     # 公開鍵
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config

WARNING: UNPROTECTED PRIVATE KEY FILE! が出たらこれが原因。

共有開発ディレクトリ

bash
# 共有プロジェクトスペースを作成
sudo mkdir -p /opt/projects/32blog
sudo chown -R :developers /opt/projects/32blog
sudo chmod -R 2775 /opt/projects/32blog

# チームメンバーをグループに追加
sudo usermod -aG developers furuya
sudo usermod -aG developers colleague

2775 + setgidの組み合わせ: developers グループの全員が読み書きでき、新規ファイルは自動的に developers グループに属する。

Dockerとコンテナの権限

bash
# よくあるDockerボリュームの権限問題を修正
# コンテナがUID 1000で動くのにホスト側がroot所有の場合
sudo chown -R 1000:1000 ./docker-volumes/

# Dockerfileでの非rootユーザーパターン
# RUN useradd -r -u 1000 appuser && \
#     chown -R appuser:appuser /app

Next.jsデプロイ用の権限修正スクリプト

bash
#!/bin/bash
# fix-permissions.sh — 32blogデプロイ後に実行
set -euo pipefail

WEBROOT="/var/www/32blog"
OWNER="deploy"
GROUP="www-data"

echo "所有権を修正中..."
sudo chown -R "${OWNER}:${GROUP}" "${WEBROOT}"

echo "ディレクトリ権限を設定中..."
find "${WEBROOT}" -type d -exec chmod 2755 {} +

echo "ファイル権限を設定中..."
find "${WEBROOT}" -type f -exec chmod 644 {} +

echo "スクリプトに実行権限を付与..."
find "${WEBROOT}/scripts" -name "*.sh" -exec chmod 755 {} +

echo "完了: ${WEBROOT} の権限を修正しました"

権限の監査

bash
# ワールドライタブルなファイルを検索(セキュリティリスク)
find /var/www -perm -o=w -type f 2>/dev/null

# 所有者のいないファイル(ユーザー削除後に残った孤児)
find / -nouser -o -nogroup 2>/dev/null

# 直近24時間に変更されたファイル(インシデント対応)
find /var/www -mtime -1 -type f -ls

# setuid/setgidバイナリの一覧
find / -perm /6000 -type f -ls 2>/dev/null

FAQ

chmod 777 は具体的に何をする?なぜ避けるべき?

chmod 777 はシステム上の全ユーザーに読み取り・書き込み・実行の全権限を与える。Linuxのパーミッションモデルを完全に無効化するのと同じ。Webサーバーで侵害されたプロセスがアプリケーションコードを改ざんできてしまう。正当な用途は /tmp(スティッキービットで保護される)くらい。777の代わりに、必要なユーザーやグループを特定して chmod 775 + 適切なグループ所有権で対応しよう。

chmodとchownの違いは?

chmod何ができるか(読み取り・書き込み・実行)を制御する。chown誰のものか(ユーザーとグループ)を制御する。セットで使う: まず chown で所有者を決めて、chmod で権限を定義する。chmod はファイルの所有者なら一般ユーザーでも実行できるが、chown は基本的にroot権限が必要。

スクリプトで "Permission denied" が出る場合の対処法は?

まず実行ビットを確認: ls -l script.sh-rw-r--r--x がない)なら chmod +x script.sh で追加。それでもダメなら親ディレクトリを確認——/ からスクリプトまでのパス上の全ディレクトリに実行権限が必要。

数値(755)とシンボリック(u=rwx,go=rx)のどちらを使うべき?

結果は全く同じ。数値はタイプが速く、ドキュメントでよく使われる。シンボリックは読みやすく、部分的な変更が安全——chmod g+w file はグループの書き込みだけ追加して他に影響しない。多くのシステム管理者は、全権限の設定には数値を、個別ビットの調整にはシンボリックを使い分けている。

ファイルの現在の権限を確認する方法は?

ls -l file でシンボリック形式を表示。数値で見たい場合は stat -c "%a %n" file(Linux)または stat -f "%Lp %N" file(macOS)。ACL(基本権限を超えたアクセス制御リスト)を確認するには getfacl file

権限表示の 's' は何を意味する?

所有者の位置にあればsetuid、グループの位置にあればsetgidを示す。rwsr-xr-x は、誰が実行しても所有者の権限で動くという意味——passwd のようにroot権限が必要なシステムコマンドで使われる。ディレクトリのグループ位置の s は、新規ファイルがディレクトリのグループを継承することを意味する。

SSHが鍵の権限について警告を出す理由は?

SSHはセキュリティのため厳格な権限を要求する。秘密鍵は 600(所有者のみ読み書き)、.ssh ディレクトリは 700authorized_keys600 でなければならない。どれかが緩いとSSHは鍵の使用を拒否する。chmod 600 ~/.ssh/id_*chmod 700 ~/.ssh で修正。

ACLを使うべきタイミングは?

3つのカテゴリ(所有者・グループ・その他)では足りないとき。標準パーミッションではファイルに1グループしか割り当てられない。ACL(setfacl/getfacl)を使えば、複数の特定ユーザーやグループに異なる権限を設定できる。よくあるケース: グループAに読み取り権限、グループBに読み書き権限を与えたい。標準パーミッションでは無理——ACLならできる。Red HatのLinux ACL入門が詳しい。

まとめ

Linuxの権限管理は2つの問いに集約される: 「誰のものか?」(chown)と「何ができるか?」(chmod)。90%の場面で使うパターン:

  • Webサーバー: chown deploy:www-data、ディレクトリ 2755、ファイル 644
  • SSH鍵: 秘密鍵 chmod 600、公開鍵 644、ディレクトリ 700
  • 共有ディレクトリ: chown :groupchmod 2775 でsetgid付きグループ書き込み
  • スクリプト: chmod +x で実行可能に

最小権限の原則を出発点にする——必要な最低限の権限だけを付与。何か壊れたら ls -lstat で診断。もっと広範囲に権限の問題を調べたいときは、find-perm オプションでファイルシステム全体を走査できる。