When using self-hosted GitHub Actions runners, you may encounter permission errors when trying to remove or modify files in the workspace:
Error: EACCES: permission denied, unlink '/home/actions-runner/_work/ipfs_datasets_py/ipfs_datasets_py/.github/GITHUB_ACTIONS_FIX_GUIDE.md'
Error: fatal: Unable to create '/path/to/.git/index.lock': Permission denied
- Stale git lock files from interrupted workflows
- Permission mismatches between runner user and workspace files
- Git processes not properly terminated
- Insufficient permissions on
.gitand.githubdirectories
Run this command on the runner host machine:
# Navigate to your ipfs_accelerate_py directory
cd /home/barberb/ipfs_accelerate_py
# Run the fix script
./.github/scripts/fix_runner_permissions.shOr for a specific runner:
./.github/scripts/fix_runner_permissions.sh /home/actions-runnerThe repository includes an automated cleanup workflow that runs every 6 hours.
File: .github/workflows/runner-cleanup.yml
Features:
- Automatically cleans workspace every 6 hours
- Removes stale git lock files
- Fixes permissions on
.gitand.githubdirectories - Cleans Python cache files
- Reports disk usage
- Can be triggered manually
Manual trigger:
gh workflow run runner-cleanup.ymlAdd the cleanup action as the FIRST step in your workflow jobs:
jobs:
your-job:
runs-on: [self-hosted, linux, arm64]
steps:
# IMPORTANT: This must be the first step!
- name: Pre-job cleanup
uses: ./.github/actions/cleanup-workspace
- name: Checkout code
uses: actions/checkout@v4
with:
clean: true # Always use clean checkout
fetch-depth: 1
# ... rest of your workflow stepsWhat this does:
- Removes stale git lock files
- Fixes .git directory permissions
- Fixes .github directory permissions
- Cleans Python cache
- Reports disk usage
Use the provided script for manual cleanup:
Location: .github/scripts/fix_runner_permissions.sh
Usage:
# Fix all runners
./.github/scripts/fix_runner_permissions.sh
# Fix specific runner
./.github/scripts/fix_runner_permissions.sh /home/barberb/actions-runner-datasets
# Show help
./.github/scripts/fix_runner_permissions.sh --helpWhat it does:
- Removes all git lock files
- Fixes git directory permissions recursively
- Fixes .github directory permissions
- Cleans Python cache files
- Fixes ownership to current user
- Reports summary of actions taken
Update your existing workflows to include pre-job cleanup. Here's an example:
jobs:
test:
runs-on: [self-hosted, linux, arm64]
steps:
- uses: actions/checkout@v4
- name: Run tests
run: pytestjobs:
test:
runs-on: [self-hosted, linux, arm64]
steps:
- name: Pre-job cleanup
uses: ./.github/actions/cleanup-workspace
- uses: actions/checkout@v4
with:
clean: true
fetch-depth: 1
- name: Run tests
run: pytest- uses: actions/checkout@v4
with:
clean: true # Forces clean checkout
fetch-depth: 1 # Shallow clone for speedEvery job on self-hosted runners should start with:
- name: Pre-job cleanup
uses: ./.github/actions/cleanup-workspaceSet up monitoring:
# View runner logs
tail -f /home/actions-runner/_diag/Runner*.log
# Check for permission errors
grep -i "permission\|eacces" /home/actions-runner/_diag/Worker*.logThe automated cleanup workflow runs every 6 hours, but you can also:
-
Add a cron job on the runner host:
# /etc/cron.daily/cleanup-runners #!/bin/bash /home/barberb/ipfs_accelerate_py/.github/scripts/fix_runner_permissions.sh
-
Manually trigger cleanup before important workflows:
gh workflow run runner-cleanup.yml
Error:
Error: EACCES: permission denied, unlink '/path/to/file'
Solution:
# On the runner host, fix permissions for that specific file
chmod u+rw /path/to/file
# Or fix the entire workspace
./.github/scripts/fix_runner_permissions.shError:
fatal: Unable to create '/path/.git/index.lock': File exists
Solution:
# On the runner host
rm /path/to/workspace/.git/index.lock
# Or use the cleanup script
./.github/scripts/fix_runner_permissions.shError:
No space left on device
Solution:
# Check disk usage
df -h /home/actions-runner/_work
# Clean old workspaces
cd /home/actions-runner/_work
find . -type d -name "_temp" -mtime +7 -exec rm -rf {} +After applying any fix, test with these steps:
-
Trigger a workflow manually:
gh workflow run <your-workflow.yml>
-
Check the workflow logs for permission errors
-
Verify cleanup worked:
# On runner host cd /home/actions-runner/_work find . -name "*.lock" # Should return nothing
gh run list --workflow=runner-cleanup.yml
gh run view <run-id>cd /home/actions-runner
./run.sh --once # Test runner# Add to crontab for daily reports
0 9 * * * df -h /home/actions-runner/_work | mail -s "Runner Disk Usage" admin@example.comThis fix includes the following files:
.github/scripts/fix_runner_permissions.sh- Manual cleanup script.github/workflows/runner-cleanup.yml- Automated cleanup workflow.github/actions/cleanup-workspace/action.yml- Reusable cleanup action.github/actions/cleanup-workspace/README.md- Action documentationRUNNER_PERMISSION_FIX_GUIDE.md- This guide (you're reading it!)
./.github/scripts/fix_runner_permissions.sh- Add pre-job cleanup to all workflows
- Use clean checkout with
clean: true - Let automated cleanup workflow run every 6 hours
- Monitor runner health regularly
- Run the manual fix script once
- Add cleanup action to workflow files
- Enable automated cleanup workflow
- Use
clean: truein checkout actions - Set up monitoring/alerts
- Test workflows after changes
- RUNNER_PERMISSION_FIX.md - Original issue documentation
- .github/workflows/README_DOCUMENTATION_MAINTENANCE.md
- GitHub Actions Documentation
- Self-hosted Runner Troubleshooting
If you continue to experience issues:
- Check the workflow logs:
gh run view <run-id> --log - Review runner diagnostic logs:
/home/actions-runner/_diag/ - Create an issue with the
runner-supportlabel - Include error messages and runner logs