Skip to content

Linux Filesystem Hierarchy Standard FHS: The "Gold Standard" for Software Installation ​

Whether through yum,apt Whether installing packages or manually compiling source code, Linux software installation must follow a set of underlying principles—Filesystem Hierarchy Standard (FHS).

Only by following this specification can the system stay clean and avoid "dependency hell" and file clutter. This article will explain in depth where executable files, library files, configuration files, and log files should each "live."

Core Principle: Why Can’t It Be Placed Casually? ​

In Windows, software usually has its own directory (such as C:\Program Files\MyApp). But in Linux,The software's files are stored separately according to "purpose.":

  • executable program Centralized storage (convenient $PATH Search)

  • Configuration file Centralized storage (convenient for backup and management)

  • Library file Shared storage (saves disk and memory)

First-Level Directory Quick Reference Table ​

Table of ContentsFunction descriptionKey Features
/Root directory, the starting point of the file systemContains only subdirectories and does not directly store files.
/binBasic user commands (required at startup)point to /usr/bin the symbolic link (modern distributions)
/sbinSystem management commands (such as fdisk,mount)only root The user mainly uses
/etcConfiguration File Base CampText files, almost all of which are ASCII code.
/usrUnix System Resource: Main system resourcesShareable, read-only, the largest directory
/varVariable: Changing dataLogs, cache, lock files, spool files
/tmpTemporary fileIt is usually cleared after a restart.
/procVirtual file system, process informationExists in memory (does not take up disk space)

The "Golden Four Quadrants" of Software Installation ​

For manually installing or developing an application on Linux, please strictly follow the storage specifications in the following four dimensions:

1. Executable program ​

TypepathExample
System built-in/package manager/usr/bin/ls,grep,nginx
Local manual compilation/usr/local/bin/go1.22(Manual compilation version)
go install Install~/go/bin/ or $GOPATH/bingo install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Non-system-critical service/opt/<app>/bin//opt/goland/bin/goland.sh

💡 Note

/bin Usually /usr/bin the symbolic link of; do not casually put your own scripts into /usr/bin, please use /usr/local/bin.

2. Configuration file ​

This is where beginners are most likely to make mistakes.

Scope of effectPathScene
Global Configuration/etc/<appname>/nginx.conf,ssh/sshd_config
Internal default configuration of the program/usr/share/<app>/It is usually not recommended to modify it directly; you should copy it to /etc Coverage
User configuration~/.config/<app>/ or ~/.<app>rc~/.bashrc,~/.gitconfig

3. Data and Logs ​

TypepathDescription
runtime variable(e.g., PID, Socket)/run/<app>/Disappears upon restart
log file/var/log/<app>/Configuration required logrotate Prevent the hard disk from filling up
Cache data/var/cache/<app>/Can be deleted without affecting functionality
Persistent data(database, upload file)/var/lib/<app>/For example, MySQL's /var/lib/mysql

4. Static Resources and Documentation ​

Typepath
Documentation/Manual/usr/share/doc/<app>/
Help Manual(Man Pages)/usr/share/man/man1/
Icon/Desktop shortcut/usr/share/applications/(used for GUI)

Hands-on: Package an item named myapp example of ​

Suppose you wrote a daemon in Go called myapp, the standard deployment structure is as follows:

bash
# 1. Binary file (Go build artifact)
/usr/local/bin/myapp

# 2. Configuration file
/etc/myapp/config.yaml
/etc/myapp/plugins/   # Sub-configuration directory

# 3. systemd service file (make it start on boot)
/usr/lib/systemd/system/myapp.service

# 4. Logs (automatically generated when the program runs)
/var/log/myapp/access.log
/var/log/myapp/error.log

# 5. Data persistence (if it is a storage-type application)
/var/lib/myapp/database.db

Example of the corresponding Go program reading configuration ​

go
package main

import (
    "fmt"
    "os"
    "gopkg.in/yaml.v3"
)

type Config struct {
    Server struct {
        Port int `yaml:"port"`
    } `yaml:"server"`
    Database struct {
        Path string `yaml:"path"`
    } `yaml:"database"`
}

func main() {
    // Standard path: /etc/myapp/config.yaml
    configPath := "/etc/myapp/config.yaml"

    data, err := os.ReadFile(configPath)
    if err != nil {
        // Fall back to reading the local development configuration
        data, err = os.ReadFile("./config.yaml")
        if err != nil {
            panic(fmt.Sprintf("failed to read configuration: %v", err))
        }
    }

    var config Config
    if err := yaml.Unmarshal(data, &config); err != nil {
        panic(fmt.Sprintf("failed to parse configuration: %v", err))
    }

    fmt.Printf("Server port: %d\n", config.Server.Port)
}

corresponding systemd Service file example ​

ini
[Unit]
Description=My Go App
After=network.target

[Service]
Type=simple
User=myapp
Group=myapp
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.yaml

# Security hardening - Restrict filesystem access
ReadWritePaths=/var/lib/myapp /var/log/myapp
ReadOnlyPaths=/etc/myapp

[Install]
WantedBy=multi-user.target

Targeting /opt and /usr/local Selection suggestions ​

Readers searching for this question often struggle with: Where should I put my third-party closed-source software?

SceneRecommended catalogReason
Source code compilation (go build+make install)/usr/localThis is /usr local supplement to it; the package manager will not overwrite it.
Unzip and use(Go single-file binary)/opt or /usr/local/bin/opt Suitable for large static software packages; a single file can be placed directly.bin.
commercial software(e.g., GoLand, Datadog Agent)/opt/<company>FHS explicitly specifies /opt Used to attach application software packages.
Packages not available in the distribution repository(e.g., manually install Docker)/usr/local/binMaintain /usr/bin Clean.

Common Errors and Corrections ​

  • Error:go build -o ~/myapp Then put the binary in the home directory and invoke it via an absolute path.

  • Consequences: Regular users cannot pass sudo systemctl Management, the environment variable PATH cannot be found.

  • Correct: For use in production environment /usr/local/bin or /opt.

  • Error: Write the log file in the program installation directory (e.g.,/opt/myapp/logs/) below.

  • Consequences Log rotation tool (logrotate) default monitoring /var/log; When running as an unprivileged user, insufficient permissions may prevent log writing.

  • Correct: Strictly comply /var/log.

  • Error: Manual modification /usr/share/ default configuration under.

  • consequences: Software upgrade (overwrite /usr/share when), your changes will be lost.

  • Correct: Copy the configuration to /etc/ or in /etc/ Create a file with the same name in it to overwrite.

Quick memorization mnemonic ​

binary search bin, find configuration etc,

Log search var, static search share,

Compile it yourself.local, big tech software release opt.

View the current system's FHS implementation ​

You can use the following command to see how your Linux distribution organizes directories:

bash
# View the mount point of the top-level directory
ls -lh /

# Check whether /bin is a symlink (usually it is in modern distributions)
file /bin

# Check where the files installed by a package go (using nginx as an example)
# Based on RPM (CentOS/RHEL):
rpm -ql nginx

# Based on DEB (Ubuntu/Debian):
dpkg -L nginx

📚References Filesystem Hierarchy Standard (FHS 3.0) — The Linux Foundation

Last updated on11/07/2026, 02:16 PM
@fishfinal | @fishfinals | [email protected]