Skip to content

ctsit/redcap_upgrade_permissions

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

redcap_upgrade_permissions

A PHP CLI utility for Linux that manages filesystem permissions on a REDCap installation, hardening Apache's access during normal operation and temporarily restoring write access during upgrades and external module installations.

Background

REDCap's built-in upgrade wizard and external module installer require the Apache process to write files inside the application directory. Leaving those permissions open permanently is a security risk. This tool automates the two-state permission model:

State Owner Group Dirs Files Apache access
Locked (normal) root www-data 0750 0640 Read-only
Unlocked (upgrade) www-data www-data 0750 0640 Read + write

Write access is granted by changing ownership, not by loosening mode bits, so permissions stay tight in both states.

Certain paths are handled specially regardless of state:

  • Always protecteddatabase.php is always owned by the locked owner so DB credentials are never writable by Apache.
  • Always writablemodules/orca_search_v* directories are always owned by the Apache user so the OrcaSearch external module can write its data files even while the rest of the application is locked.
  • Always writabletemp/ directory is always owned by the Apache user so the Apache (and REDCap) can write its data files even while the rest of the application is locked.

Requirements

  • Linux host running Apache
  • PHP 8.1 or later (CLI)
  • Must be run as root (via sudo)

Installation

  1. Copy the script to a location on the system path:

    sudo cp redcap_upgrade_permissions.php /usr/local/bin/redcap_upgrade_permissions.php
    sudo chmod 0755 /usr/local/bin/redcap_upgrade_permissions.php
  2. Save your site-specific options so you don't have to repeat them on every invocation (this also sets up the config for the cron job):

    sudo php /usr/local/bin/redcap_upgrade_permissions.php status \
        --path=/var/www/html/redcap --timeout=180 --save-options

    Options that differ from the defaults (e.g. --apache-user, --owner, --timeout) should be included here. The saved config file is read automatically on every subsequent run.

  3. Lock the filesystem to establish the initial safe state:

    sudo php /usr/local/bin/redcap_upgrade_permissions.php lock
  4. Optionally add a cron job to auto-relock if the unlock timeout expires without a manual lock command (runs every minute, silent unless an action is taken):

    * * * * * root php /usr/local/bin/redcap_upgrade_permissions.php relock --no-color
    

Usage

sudo php redcap_upgrade_permissions.php <command> [options]

Commands

Command Description
lock Restrict permissions — Apache read-only. The normal, safe state.
unlock Grant Apache write access for an upgrade. Records unlock time for auto-relock.
status Show current state, remaining unlock time, and a live filesystem sample.
relock Re-lock if the unlock timeout has expired. Designed for cron.

Options

Option Default Description
--path=<dir> /var/www/html/redcap REDCap installation directory
--apache-user=<user> www-data Apache process user
--apache-group=<grp> www-data Apache process group
--owner=<user> root File owner when locked
--timeout=<seconds> 1200 Auto-relock after N seconds when unlocked
--state-file=<path> /var/run/redcap_perms.state Unlock state file location
--log-file=<path> /var/log/redcap_perms.log Log file location
--config=<path> /etc/redcap_upgrade_permissions.conf Config file for saved options
--save-options Save --path, --apache-user, --apache-group, --owner, --timeout, and --state-file to the config file, then run the command normally
--dry-run Print commands without executing them
--yes Skip confirmation prompts (non-interactive/scripted use)
--force Override skip conditions: reapply if already in state, reset unlock timer, or relock before timeout expires
--no-color Disable ANSI color output (recommended for cron/scripts)
--help Show help message

Typical Upgrade or Module Installation Workflow

# 1. Verify the current state before starting
sudo php redcap_upgrade_permissions.php status --path=/var/www/html/redcap

# 2. Open write access (20-minute window by default)
sudo php redcap_upgrade_permissions.php unlock --path=/var/www/html/redcap

# 3. Run the REDCap upgrade or external module installation through the browser

# 4. Re-lock immediately once the upgrade or installation is complete
sudo php redcap_upgrade_permissions.php lock --path=/var/www/html/redcap

# 5. Verify
sudo php redcap_upgrade_permissions.php status --path=/var/www/html/redcap

Additional Examples

# Preview what 'unlock' would do without making any changes
sudo php redcap_upgrade_permissions.php unlock --path=/var/www/html/redcap --dry-run

# Unlock with a custom 2-hour window, skipping the confirmation prompt
sudo php redcap_upgrade_permissions.php unlock --path=/var/www/html/redcap \
    --timeout=7200 --yes

# Use non-standard Apache user/group (e.g. RHEL/CentOS)
sudo php redcap_upgrade_permissions.php unlock --path=/var/www/html/redcap \
    --apache-user=apache --apache-group=apache

# Force re-lock immediately (e.g. if you forgot to lock after an upgrade)
sudo php redcap_upgrade_permissions.php relock --path=/var/www/html/redcap --force

Saving Options and Multiple Instances

Use --save-options with any command to persist the six configurable options (--path, --apache-user, --apache-group, --owner, --timeout, --state-file) to a JSON config file. Saved values become the new defaults and are automatically loaded on every subsequent run.

# Save options for your site (run once after installation)
sudo php redcap_upgrade_permissions.php status --path=/var/www/html/redcap \
    --apache-user=apache --apache-group=apache --save-options

# All subsequent commands pick up saved options automatically
sudo php redcap_upgrade_permissions.php unlock

To manage two REDCap instances on the same host, use a separate --config file for each. The --state-file option (also saved) keeps the unlock state for each instance independent.

# Configure and save options for a second instance
sudo php redcap_upgrade_permissions.php status \
    --config=/etc/redcap2_upgrade_permissions.conf \
    --path=/var/www/html/redcap2 \
    --state-file=/var/run/redcap2_perms.state \
    --save-options

# Operate on the second instance by pointing at its config file
sudo php redcap_upgrade_permissions.php unlock \
    --config=/etc/redcap2_upgrade_permissions.conf

# Cron entry for the second instance
* * * * * root php /usr/local/bin/redcap_upgrade_permissions.php relock \
    --config=/etc/redcap2_upgrade_permissions.conf --no-color

State and Logging

  • State file (/var/run/redcap_perms.state) — JSON file recording whether the installation is locked and when it was unlocked. Used by status and relock. Readable only by root (0600).
  • Log file (/var/log/redcap_perms.log) — Append-only log of every lock, unlock, and auto-relock action with timestamp and invoking user.

License

Copyright 2026 University of Florida. Licensed under the Apache License, Version 2.0.

About

Manages Linux filesystem permissions for a REDCap installation to restrict Apache write access during normal operation and temporarily re-open it during upgrades.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages