chmod 640

rw-r-----

chmod 640 sets the mode to rw-r-----: the owner can read and write (6), the group can read (4), and everyone else gets nothing (0). It’s the mode for a file that one account maintains, one group of services reads, and nobody else should see: configuration with passwords, logs, private keys a daemon loads.

The usual pattern: root owns, the service’s group reads

sudo chown root:myapp /etc/myapp/config.env
sudo chmod 640 /etc/myapp/config.env
stat -c '%a %U:%G %n' /etc/myapp/config.env   # 640 root:myapp /etc/myapp/config.env

The service, running as a user in group myapp, can read its database password but can’t rewrite its own configuration. Other local users and any other compromised service can’t read it at all.

Where the system already uses it

  • /etc/shadow on Debian and Ubuntu is 640, owned by root:shadow, so tools in the shadow group can check passwords without being root.
  • Logs. On Ubuntu, /var/log/syslog is 640 and owned by syslog:adm, so members of adm can read logs without sudo. logrotate recreates rotated logs that way with a create line, as in Debian’s nginx config: create 0640 www-data adm.
  • TLS keys on Debian. /etc/ssl/private belongs to group ssl-cert, and the snakeoil key in it is 640, so a daemon added to ssl-cert can load it.

Gotchas

  • SSH keys want stricter. OpenSSH refuses a private key with any group access: Permissions 0640 ... are too open. Use 600 or 400 for keys that ssh itself loads.
  • The group decides everything. 640 with group users or staff is close to world-readable. Check the group with ls -l, and its members with getent group myapp.
  • Directories need execute. A 640 directory can’t be entered; the matching directory mode is 750.
  • New group members get access only at their next login, or after a service restart.

Umask, git and containers

Umask 027 gives this mode: 666 with 027 cleared is 640, and directories become 750. Setting UMask=0027 in a systemd unit makes a service’s own logs and files come out that way.

Git doesn’t keep it: a 640 file is stored as 100644 and checked out as 644, readable by everyone, so set modes in the deploy step. In a Dockerfile, COPY --chown=root:app --chmod=640 config.env /etc/app/ sets owner and mode together. In Kubernetes, defaultMode: 0640 is 416 in JSON.

Try it in the chmod Calculator

640 rw-r-----

WhoReadWriteExecute
Owner
Group
Others
Special bits
Command
chmod 640 file

Runs in your browser. Nothing you enter is sent anywhere.