Files
ngit-grasp/b454-nixos-module-execstartpre-datadir.md
T
2026-01-20 09:14:26 +00:00

180 lines
6.7 KiB
Markdown

# NixOS module should auto-create data directories in ExecStartPre
**ID:** b454
## Problem
When adding a new ngit-grasp instance with a custom `dataDir` (e.g., `/persistent/grasp/archive`), the service fails to start with:
```
status=226/NAMESPACE
ngit-grasp-archive.service: Failed to set up mount namespacing: /persistent/grasp/archive: No such file or directory
```
Root cause: The NixOS module creates tmpfiles rules for the data directory, but these rules aren't automatically executed during `nixos-rebuild switch`. Users must manually run `sudo systemd-tmpfiles --create --prefix=/path/to/dataDir`.
## Plan
- [x] Phase 1: Add `ExecStartPre` to systemd service configuration in `nix/module.nix`
- [x] Phase 2: Create directories before service starts (dataDir, dataDir/git, dataDir/relay)
- [x] Phase 3: Set proper ownership and permissions
- [x] Phase 4: Investigate if there are specific custom path options for git and relay data directories
- Confirmed: No separate options exist; git/relay paths are derived from dataDir
- [x] Phase 5: Update ExecStartPre logic to handle those paths if they exist
- N/A: Paths are always `${dataDir}/git` and `${dataDir}/relay`
## Implementation
Add to `nix/module.nix` in the `mkService` function:
```nix
serviceConfig = {
# ... existing config ...
# Ensure data directories exist before service starts
ExecStartPre = [
"+${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}'"
"+${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}/git'"
"+${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}/relay'"
"+${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} '${cfg.dataDir}'"
"+${pkgs.coreutils}/bin/chmod 750 '${cfg.dataDir}'"
"+${pkgs.coreutils}/bin/chmod 750 '${cfg.dataDir}/git'"
"+${pkgs.coreutils}/bin/chmod 750 '${cfg.dataDir}/relay'"
];
};
```
## Benefits
- Guarantees directories exist before service starts
- Works for any path (including `/persistent/`, `/var/lib/`, etc.)
- Follows established NixOS patterns (silverbullet, icecast, logstash)
- Negligible performance impact
- Eliminates confusing failure mode
## Progress
### 2026-01-20 [Session 10:30] - Verification Complete
- Completed: All verification tests passed successfully
- Verified: ExecStartPre directives work correctly on NixOS deployment
- Tested: Fresh install, idempotency, permission correction, ownership correction
- Result: Service starts successfully with auto-created directories
- Status: Ready to merge to main
### 2026-01-20 [Session 09:00] - Testing Strategy Review
- Reviewed: Implementation in commit f93fc0a691544cc3ddda322a7e99d0534d636dcc
- Designed: Comprehensive testing strategy for NixOS deployment
#### Testing Strategy
**Approach:** Add a test ngit-grasp instance with `archiveAll = true` to the user's NixOS configuration. This will:
1. Test the ExecStartPre directory creation with a fresh custom dataDir
2. Exercise the git directory creation when archive mode accepts repositories
3. Validate permissions are correct for service operation
**Test Scenarios:**
1. **Fresh Install (Primary Test)**
- Add new instance with non-existent custom dataDir (e.g., `/persistent/grasp/test-archive`)
- Run `nixos-rebuild switch`
- Expected: Service starts successfully, directories created with correct ownership
2. **Existing Directories (Idempotency)**
- Restart the service after initial setup
- Expected: ExecStartPre completes without errors, permissions unchanged
3. **Permission Correction**
- Manually change directory permissions (e.g., `chmod 777`)
- Restart service
- Expected: Permissions reset to 750
4. **Ownership Correction**
- Manually change ownership (e.g., `chown root:root`)
- Restart service
- Expected: Ownership reset to service user:group
**Recommended Test Configuration:**
```nix
# Add to NixOS configuration alongside existing ngit-grasp instances
services.ngit-grasp.test-archive = {
enable = true;
domain = "test-archive.localhost"; # Won't be publicly accessible
port = 7335; # Different port from production
dataDir = "/persistent/grasp/test-archive"; # Fresh path that doesn't exist
archiveAll = true; # Enables archive mode for testing git operations
logLevel = "debug"; # Verbose logging for verification
};
```
**Verification Commands:**
```bash
# 1. Check service status
sudo systemctl status ngit-grasp-test-archive
# 2. Verify directories exist with correct permissions
ls -la /persistent/grasp/test-archive/
# Expected: drwxr-x--- ngit-grasp-test-archive ngit-grasp
ls -la /persistent/grasp/test-archive/git/
ls -la /persistent/grasp/test-archive/relay/
# Expected: drwxr-x--- ngit-grasp-test-archive ngit-grasp
# 3. Check ExecStartPre execution in journal
journalctl -u ngit-grasp-test-archive --no-pager | head -50
# 4. Test permission correction
sudo chmod 777 /persistent/grasp/test-archive
sudo systemctl restart ngit-grasp-test-archive
stat /persistent/grasp/test-archive
# Expected: 0750 permissions restored
# 5. Test ownership correction
sudo chown root:root /persistent/grasp/test-archive
sudo systemctl restart ngit-grasp-test-archive
stat /persistent/grasp/test-archive
# Expected: ngit-grasp-test-archive:ngit-grasp ownership restored
```
**Cleanup After Testing:**
```bash
# Remove test instance from NixOS config, then:
sudo nixos-rebuild switch
sudo rm -rf /persistent/grasp/test-archive
sudo userdel ngit-grasp-test-archive # If user persists
```
**Edge Cases to Consider:**
- Parent directory doesn't exist (e.g., `/persistent/grasp/` doesn't exist)
- `mkdir -p` handles this correctly
- Symlinked dataDir paths
- Should work, but worth verifying
- SELinux/AppArmor contexts (if enabled)
- May need additional testing on hardened systems
### 2026-01-20 [Session 08:15]
- Completed: Implemented ExecStartPre directives in nix/module.nix
- Implementation details:
- Added 7 ExecStartPre commands with `+` prefix (runs as root)
- Creates dataDir, dataDir/git, dataDir/relay with mkdir -p
- Sets ownership with chown -R to cfg.user:cfg.group
- Sets permissions 750 on all three directories
- Decision: Kept existing tmpfiles.rules for boot-time setup and consistency
- Verified: No separate git/relay path options exist; they're always derived from dataDir
### 2026-01-20 [Session 07:41]
- Started work: Created worktree for implementation
### 2026-01-19 [Session 00:00]
- Started: Issue created to track NixOS module enhancement for automatic data directory creation
## Notes
- Keep existing tmpfiles.rules for consistency and boot-time setup
- The + prefix in ExecStartPre runs as root for directory creation
- Discovered during relay.ngit.dev migration planning (issue 820a)
- Additional investigation needed: Check if the module has (or should have) separate config options for git data directory path and relay data directory path