| layout | title | nav_order | mermaid |
|---|---|---|---|
default |
File System Layout |
6 |
true |
{: .note }
✅ Validated against Unraid 7.2.3 - Directory structures and paths verified on live systems.
Understanding where files are stored and why is crucial for Unraid plugin development. Unraid runs from RAM, which creates unique challenges and opportunities.
Unraid boots from a USB flash drive into RAM. This means:
- Changes to most files are lost on reboot
- The USB flash drive is the only persistent storage during boot
- Plugins must be reinstalled on every boot
flowchart TB
subgraph USB["USB Flash Drive /boot"]
subgraph Persistent["Persistent - survives reboot"]
P1["/boot/config/plugins/myplugin/"]
P2["myplugin.cfg (user settings)"]
P3["myplugin-package.txz (cached)"]
end
end
USB -->|"Installed on boot"| RAM
subgraph RAM["RAM Disk"]
subgraph Volatile["Volatile - rebuilt each boot"]
R1["/usr/local/emhttp/plugins/myplugin/"]
R2["myplugin.page (web UI)"]
R3["scripts/ (shell scripts)"]
R4["php/ (PHP code)"]
end
end
style USB fill:#4a9eff,color:#fff
style RAM fill:#ff9800,color:#fff
style Persistent fill:#4caf50,color:#fff
style Volatile fill:#f44336,color:#fff
{: .placeholder-image }
📷 Screenshot needed: File listing of /boot/config/plugins/ directory
Location: USB Flash Drive
Persistence: ✅ Survives reboot
This is where plugin files are stored on the boot device:
/boot/config/plugins/
├── myplugin.plg # The plugin installer file
├── myplugin/ # Plugin's persistent storage
│ ├── myplugin.cfg # User configuration
│ ├── myplugin-package-1.0.txz # Cached package (optional)
│ └── data/ # Plugin data files
└── [other-plugins...]
Use for:
- User configuration files
- Cached downloads (packages, icons)
- Small data files that must persist
- State files
Avoid:
- Large data files (limited USB space)
- Frequently written files (USB wear)
- Log files
{: .placeholder-image }
📷 Screenshot needed: File listing of /boot/config/plugins/ directory
Location: RAM Disk
Persistence: ❌ Rebuilt on boot
This is where active plugin files live:
/usr/local/emhttp/plugins/myplugin/
├── myplugin.page # Main UI page
├── myplugin.settings.page # Settings page
├── default.cfg # Default configuration
├── README.md # Shown in Plugin Manager
├── php/
│ ├── exec.php # AJAX endpoint
│ └── helpers.php # Utility functions
├── scripts/
│ ├── start.sh # Service start script
│ └── status.sh # Status check
├── event/
│ ├── started # Array started handler
│ └── stopping_docker # Pre-Docker-stop handler
├── javascript/
│ └── custom.js # Client-side scripts
└── styles/
└── custom.css # Plugin styles
Contains:
- Web UI pages (
.pagefiles) - PHP scripts
- Shell scripts
- Event handlers
- Static assets (JS, CSS, images)
- Default configuration
{: .placeholder-image }
📷 Screenshot needed: File listing of /usr/local/emhttp/plugins/ structure
Location: RAM Disk
Persistence: ❌ Cleared on reboot
Contains symlinks indicating which plugins are installed:
/var/log/plugins/
├── myplugin.plg -> /boot/config/plugins/myplugin.plg
└── [other-plugins.plg...]
The plugin manager checks this directory to know what's installed.
Location: RAM Disk
Persistence: ❌ Temporary
Used during plugin operations:
- Downloaded plugin files for updates
- Temporary extraction location
Special directories on the USB flash:
| Directory | Purpose |
|---|---|
/boot/config/plugins/ |
Active plugins |
/boot/config/plugins-error/ |
Plugins that failed to install |
/boot/config/plugins-removed/ |
Uninstalled plugins |
/boot/config/plugins-stale/ |
Superseded plugin versions |
Store user settings on the USB flash:
/boot/config/plugins/myplugin/myplugin.cfg
Format:
SETTING_ONE="value"
SETTING_TWO="another value"
ENABLED="true"Reading in PHP:
$cfg = parse_plugin_cfg('myplugin');
echo $cfg['SETTING_ONE'];For larger data that needs to persist:
Option 1: User Share (Recommended)
/mnt/user/appdata/myplugin/
Option 2: Cache Drive
/mnt/cache/appdata/myplugin/
Option 3: Array Share
/mnt/user/myplugin-data/
Use the system logger (writes to RAM, available in syslog):
logger "myplugin: Your log message"
logger -t myplugin "Tagged message"Or write to a temporary file:
echo "Log message" >> /tmp/myplugin.logFor PID files, state tracking:
# PID file
/var/run/myplugin.pid
# Lock files
/var/lock/myplugin.lock
# Temporary state
/tmp/myplugin/When building your package:
# Make scripts executable
chmod +x scripts/*.sh
chmod +x event/*
# Standard file permissions
chmod 644 *.page
chmod 644 *.cfg
chmod 644 php/*.php
# Make PHP exec scripts executable
chmod +x php/exec.phpUser config files on flash:
# Secure user config
chmod 600 /boot/config/plugins/myplugin/myplugin.cfgYour .txz package should extract to mirror the emhttp structure:
[package root]/
└── usr/
└── local/
└── emhttp/
└── plugins/
└── myplugin/
├── myplugin.page
├── default.cfg
└── [other files]
Additional files can go elsewhere:
[package root]/
├── usr/
│ ├── local/
│ │ ├── emhttp/
│ │ │ └── plugins/
│ │ │ └── myplugin/
│ │ └── bin/
│ │ └── mytool # CLI utility
│ └── lib/
│ └── docker/
│ └── cli-plugins/
│ └── docker-myplugin # Docker CLI plugin
└── install/
└── slack-desc # Package description
The USB flash has limited write cycles:
# Bad - writes on every call
echo "$value" > /boot/config/plugins/myplugin/counter.txt
# Good - write to RAM, sync occasionally
echo "$value" > /tmp/myplugin/counter.txt
# Only sync to flash on shutdown or periodicallyLink from flash to RAM for frequently accessed data:
# During install script
if [ ! -L /boot/config/plugins/myplugin/logs ]; then
mkdir -p /tmp/myplugin/logs
ln -s /tmp/myplugin/logs /boot/config/plugins/myplugin/logs
fiFiles on flash may not exist on first install:
#!/bin/bash
# Create directories if needed
mkdir -p /boot/config/plugins/myplugin
# Source config with fallback
if [ -f /boot/config/plugins/myplugin/myplugin.cfg ]; then
source /boot/config/plugins/myplugin/myplugin.cfg
fiIn your remove script:
# Remove plugin files
rm -rf /boot/config/plugins/myplugin
# Remove runtime files
rm -rf /tmp/myplugin
rm -f /var/run/myplugin.pid
# Remove the package
removepkg myplugin-packageIn your README, tell users where data is stored:
## Data Locations
- **Configuration**: `/boot/config/plugins/myplugin/myplugin.cfg`
- **Application Data**: `/mnt/user/appdata/myplugin/`
- **Logs**: Check syslog with `grep myplugin /var/log/syslog`Problem: Custom files in /usr/local/emhttp/plugins/ disappear after reboot.
Solution: Files must be in your .txz package or created by an install script.
Problem: Settings don't persist.
Solution: Verify the form writes to /boot/config/plugins/yourplugin/:
<input type="hidden" name="#file" value="myplugin/myplugin.cfg">Problem: USB flash drive is full.
Solution:
- Clean
/boot/config/plugins-removed/ - Clean
/boot/config/plugins-stale/ - Move large data to array shares
- Remove cached packages you don't need
- Learn about PLG File Structure for installation
- See Packaging for creating
.txzpackages - Check Configuration Files for settings management

