Chatmail Sync
Synchronize NixOS modules with the upstream relay project.
When to use
- •User asks to sync/update modules from relay
- •User asks to check for new features in relay
- •User asks to update configurations from upstream
- •User mentions "source of truth" or "relay upstream"
Arguments
This skill accepts optional directory arguments:
| Argument | Description | Default |
|---|---|---|
--relay PATH | Path to relay repository | ../forks/relay (relative to project) |
--nixpkgs PATH | Path to nixpkgs repository | ../forks/nixpkgs (relative to project) |
Example usage:
/chatmail-sync /chatmail-sync --relay ~/projects/relay --nixpkgs ~/nixpkgs
Source paths
| Variable | Default | Description |
|---|---|---|
$RELAY_PATH | ../forks/relay relative to project | Upstream relay repository |
$PROJECT_PATH | Current working directory | This project root |
$NIXPKGS_PATH | ../forks/nixpkgs or system nixpkgs | nixpkgs for API reference |
CRITICAL: Update sources first
ALWAYS pull latest changes before any sync work.
Step 0: Update relay repository
cd "$RELAY_PATH" && git pull origin main cd "$PROJECT_PATH"
CRITICAL: Exploration first
NEVER assume you know the relay structure. ALWAYS explore thoroughly first.
Step 1: Discover relay structure
tree -a "$RELAY_PATH" -I '.git|__pycache__|*.pyc|.mypy_cache' find "$RELAY_PATH" -type f \( -name "*.conf*" -o -name "*.ini*" -o -name "*.j2" -o -name "*.toml" -o -name "*.yaml" -o -name "*.yml" -o -name "*.lua" \) find "$RELAY_PATH" -type f -name "*.service*" -o -name "*.timer*" find "$RELAY_PATH" -type f -name "*.py" | head -50
Step 2: Check recent changes
cd "$RELAY_PATH" git log --oneline -30 git diff HEAD~20 --name-only git log --oneline -10 -- chatmaild/ git log --oneline -10 -- cmdeploy/
Step 3: Deep dive into components
For EACH component you need to sync:
- •
Search for ALL related files in relay:
bashgrep -r "component_name" "$RELAY_PATH" --include="*.py" --include="*.j2" --include="*.conf*"
- •
Read the actual implementation - don't guess
- •
Check for dependencies between components
Step 4: Compare with NixOS implementation
ls -la "$PROJECT_PATH/modules/"
ls -la "$PROJECT_PATH/pkgs/"
diff <(grep -h "key_setting" "$RELAY_PATH"/**/*.j2 2>/dev/null) \
<(grep -h "key_setting" "$PROJECT_PATH/modules/"*.nix 2>/dev/null)
Step 4.5: Sync packages
grep -E "rev|hash" "$PROJECT_PATH/pkgs/chatmail-www/default.nix" cd "$RELAY_PATH" && git log --oneline -1 grep -E "version|rev|hash" "$PROJECT_PATH/pkgs/chatmaild/default.nix"
Step 5: Check nixpkgs for native support
Before implementing anything custom, check if nixpkgs has it:
find "$NIXPKGS_PATH/nixos/modules/services/" -name "*.nix" | xargs grep -l "feature_name" grep -A 20 "options\." "$NIXPKGS_PATH/nixos/modules/services/mail/dovecot.nix"
Sync checklist
Discovery phase (REQUIRED)
- • Ran
treeon relay project - • Found ALL config files (not just expected ones)
- • Found ALL systemd units
- • Checked git history for recent changes
- • Identified ALL Python modules in chatmaild
Comparison phase
- • Compared each relay component with NixOS module
- • Checked INI template vs INI generation
- • Compared systemd services
- • Compared config file contents
- • Compared package versions with relay
Extra additions phase (NixOS → relay)
- • Checked for nginx locations not in relay
- • Checked for deprecated components (
present=Falsein deployers.py) - • Searched relay for each NixOS feature to confirm it exists
- • Removed features that don't exist in relay
Implementation phase
- • Checked nixpkgs for native support first
- • Updated NixOS modules to match relay
- • Added missing options
- • Removed extra additions not in relay
- • Updated INI generation if needed
- • Updated package revisions if needed
Verification phase
- • Nix syntax is valid
- • All relay features are implemented
- • No extra features added (strict relay compatibility)
Common patterns
Finding what chatmaild reads from INI
grep -E "params\[|params\.get|self\." "$RELAY_PATH/chatmaild/src/chatmaild/config.py"
Finding how relay configures a service
grep -r "dovecot" "$RELAY_PATH" --include="*.py" --include="*.j2" --include="*.conf*" -l
Checking what ports relay uses
grep -rE "port|PORT|:([0-9]{2,5})" "$RELAY_PATH" --include="*.py" --include="*.j2" --include="*.conf*"
Finding extra additions in NixOS
grep -E "location\s+/" "$RELAY_PATH/cmdeploy/src/cmdeploy/nginx/nginx.conf.j2" grep -E '"/[^"]*"\s*=' "$PROJECT_PATH/modules/nginx.nix" grep -r "feature_name" "$RELAY_PATH" --include="*.j2" --include="*.conf*" --include="*.py"
Finding deprecated components
grep -B2 -A2 "present=False" "$RELAY_PATH/cmdeploy/src/cmdeploy/deployers.py" grep -B2 -A2 "running=False\|enabled=False" "$RELAY_PATH/cmdeploy/src/cmdeploy/deployers.py"
Known deprecated components (NOT to be implemented):
- •
mta-sts-daemon- removed from relay (present=False) - •
echobot.service- disabled in relay (running=False, enabled=False) - •
rspamd- removed from relay (present=False) - •
doveauth-dictproxy.service- legacy, replaced by doveauth.service
Checking INI options with relay defaults
Before removing or modifying any INI option, check if relay has a default:
grep -E "params\.get\(\"OPTION\"" "$RELAY_PATH/chatmaild/src/chatmaild/config.py" grep -r "config\.OPTION\|self\.OPTION" "$RELAY_PATH/chatmaild/src/chatmaild/"*.py grep -r "OPTION" "$PROJECT_PATH/modules/"*.nix
Rule:
If relay has: params.get("option", default)
And NixOS uses: different_value
Then: MUST set in INI (cannot rely on relay default)
Before removing any INI option:
- •Check if relay has
params.get()default - •Compare relay default with NixOS value
- •Check if option is used by multiple services
- •If values differ → keep in INI
Verifying each NixOS feature exists in relay
For EACH feature in NixOS modules:
- •Search for it in relay:
grep -r "feature" "$RELAY_PATH" - •If not found → it's our addition → remove it
- •If found with
present=False→ deprecated → remove it
NixOS-native vs Debian workarounds
Relay is designed for Debian/pyinfra deployment. NixOS has native declarative solutions for many things that Debian requires workarounds for.
Principle
Don't copy Debian-specific patterns. Find the NixOS-native way.
How to identify Debian workarounds in relay
grep -E "Environment=" "$RELAY_PATH/cmdeploy/src/cmdeploy/service/"*.service* grep -E "server\.shell|run_shell" "$RELAY_PATH/cmdeploy/src/cmdeploy/deployers.py" grep -E "apt\.|packages\." "$RELAY_PATH/cmdeploy/src/cmdeploy/deployers.py" find "$RELAY_PATH" -name "*.cron*" -o -name "*cron*.j2" grep -E "files\.put|files\.template" "$RELAY_PATH/cmdeploy/src/cmdeploy/deployers.py"
Decision process
For each Debian pattern found:
- •Identify the intent - what is relay trying to achieve?
- •Search nixpkgs for native support:
bash
find "$NIXPKGS_PATH/nixos/modules/" -name "*.nix" | xargs grep -l "feature"
- •If NixOS has native option → use it instead of copying Debian approach
- •If no native option → implement following relay's approach
Common patterns
| Relay Pattern | Check NixOS For |
|---|---|
Environment=VAR=... in systemd | Global NixOS option that sets this |
/etc/cron.d/* files | systemd.timers |
acmetool / certbot scripts | security.acme module |
apt install package | Service module dependencies |
useradd/groupadd | users.users/users.groups |
iptables commands | networking.firewall |
Template to /etc/file | Service's configFile or extraConfig |
Verification
Before adding any relay systemd setting to NixOS:
grep -r "SETTING_NAME" "$NIXPKGS_PATH/nixos/modules/" grep -A5 "mkOption" "$NIXPKGS_PATH/nixos/modules/services/mail/SERVICE.nix"
Output
After sync, report:
- •Files examined in relay
- •Changes made to NixOS modules
- •Package updates (rev/hash changes)
- •Features added from relay (if any)
- •Extra additions removed (features that were in NixOS but not in relay)
- •Deprecated components removed (relay has
present=False) - •Discrepancies found and resolved