* fix: add explicit bool filters for Ansible 12 jinja2_native compatibility
Ansible 12 enables jinja2_native by default, which means string values
like "true"/"false" are no longer automatically coerced to booleans in
when: conditions and Jinja2 if statements. Add | bool filters to all
boolean variable references in tasks, templates, and handlers.
Also reformats long single-line Jinja2 conditionals into multi-line for
readability, fixes GCE default() calls for native mode, adds help
command to the algo script, and updates test fixtures to register the
bool filter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ci: add j2lint for Jinja2 template linting
Add j2lint (aristanetworks/j2lint) to catch syntax errors, spacing
issues, and operator formatting in Jinja2 templates. Integrated into
pre-commit hooks, lint.yml CI, and smart-tests.yml.
Rules S3/S5/S6/S7/V1 are ignored — they enforce conventions
incompatible with Ansible's config-file-embedded templates.
Also fixes int+1 → int + 1 operator spacing in server.conf.j2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve all ansible-lint warnings and enforce zero-tolerance policy
Fix 18 jinja[spacing] errors across 12 files by moving Jinja2 block
delimiters to prevent YAML >- folding from introducing trailing spaces.
Fix 27 key-order[task] warnings across 17 files by reordering task keys
to canonical order (name → when → tags → environment → become → block).
Promote key-order[task] and yaml[line-length] from warn_list to hard
errors by removing warn_list entirely from .ansible-lint.
Add zero-tolerance warning policy to CLAUDE.md explaining why warnings
are unacceptable in a security tool and documenting resolution order.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Simplify codebase: remove dead venv files, consolidate loops, modernize patterns
- Delete 8 empty venv.yml files that were remnants of pyproject.toml migration
- Remove corresponding import_tasks references from cloud provider main.yml files
- Consolidate server.yml async polling from 4 copy-paste blocks to 1 loop
- Wrap sequential VPN service imports in a block with single when condition
- Replace deprecated with_indexed_items with modern loop/loop_control syntax
These changes reduce maintenance burden by:
- Eliminating 8 files that served no purpose
- Reducing server.yml by ~20 lines while improving readability
- Removing Ansible deprecation warnings for with_indexed_items
- Making the parallel/sequential execution paths easier to maintain
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix template variable and undefined job variable bugs
- Fix client.conf.j2 to use `item` instead of `item.1` to match modern
loop syntax (loop with index_var instead of with_indexed_items)
- Fix server.yml _vpn_jobs to use `| default({})` for job variables
that may be undefined when running with tags (e.g., IPsec-only)
- Update test_template_rendering.py to pass item as string instead of
tuple, matching the new loop behavior
Fixes CI failures from PR #14891 that were correctly identified by the
Claude Code bot review.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Simplify codebase: modernize loops, split templates, improve CI
This PR consolidates several simplification phases:
## Ansible Modernization
- Modernize `with_items` to `loop` across ~50 task files
- Add OS detection facts (is_ubuntu, os_family_lowercase)
- Condense inline YAML syntax where appropriate
## Template Splitting
- Split 568-line dnscrypt-proxy.toml.j2 into focused partials:
- global.toml.j2 (core settings)
- sources.toml.j2 (resolver sources)
- filters.toml.j2 (blocking rules)
- cache.toml.j2 (caching config)
## CI Workflow Improvements
- Create setup-algo composite action for shared CI setup
- Re-enable integration tests with health checks
- Fix smart-tests.yml silent lint failures (remove || true)
- Use env variables for GitHub SHAs (security)
## server.yml Async Simplification
- Reorganize VPN service configuration with clear sections
- Add performance_parallel_services toggle
- Simplify status display from json_query to inline conditionals
- Keep services explicit for readability
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix with_items to loop conversion: preserve list flattening
with_items automatically flattens nested lists, but loop does NOT.
The mechanical conversion broke iteration over list variables.
Wrong:
loop:
- "{{ users }}" # ['alice', 'bob'] treated as ONE item
Fixed:
loop: "{{ users }}" # Iterates over alice, bob correctly
For combined lists (users + server):
loop: "{{ users + [IP_subject_alt_name] }}"
Fixes IPsec certificate generation creating files named literally
'['alice', 'bob'].key' instead of separate alice.key and bob.key.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix integration test: use strongswan-starter service name on Ubuntu 20.04+
The StrongSwan service is named 'strongswan-starter' on Ubuntu 20.04+,
not 'strongswan'. The test was checking the wrong service name, causing
false failures even when StrongSwan was actually running.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix IPsec path issues: remove trailing slashes and fix test paths
1. Remove trailing slashes from ipsec_config_path and ipsec_pki_path
in roles/strongswan/defaults/main.yml (causes double slashes)
2. Fix integration test to check correct subdirectories:
- .p12 files are in ipsec/manual/
- .mobileconfig files are in ipsec/apple/
3. Fix strongswan service name check (strongswan-starter on Ubuntu 20.04+)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix: Add no_log to tasks handling sensitive information
- Add no_log: true to OpenSSL commands that contain passwords/passphrases
- Add no_log: true to WireGuard key generation commands
- Add no_log: true to password/CA password generation tasks
- Add no_log: true to AWS credential handling tasks
- Add no_log: true to QR code generation that contains full configs
This prevents sensitive information like passwords, private keys, and
WireGuard configurations from being logged to syslog/journald.
Fixes#1617
* feat: Comprehensive privacy enhancements
- Add no_log directives to all cloud provider credential handling
- Set privacy-focused defaults (StrongSwan logging disabled, DNSCrypt syslog off)
- Implement privacy role with log rotation, history clearing, and log filtering
- Add Privacy Considerations section to README
- Make all privacy features configurable and enabled by default
This update significantly reduces Algo's logging footprint to enhance user privacy
while maintaining the ability to enable logging for debugging when needed.
* docs: Move privacy documentation from README to FAQ
- Remove Privacy Considerations section from README
- Add expanded 'Does Algo support zero logging?' question to FAQ
- Better placement alongside existing logging/monitoring questions
- More detailed explanation of privacy features and limitations
* fix: Remove invalid 'bool' filter from Jinja2 template
The privacy-monitor.sh.j2 template was using '| bool' which is not a valid
Jinja2 filter. The 'bool' is a built-in Python function, not a Jinja2 filter.
Fixed by removing the '| bool' filter and directly outputting the boolean
variables as they will be rendered correctly by Jinja2.
This resolves the template syntax error that was causing CI tests to fail:
"No filter named 'bool'" error in privacy monitoring script template.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix YAML linting issues in privacy role
* Fix linting warnings: shellcheck and ansible-lint issues
- Fixed all shellcheck warnings in test scripts:
- Quoted variables to prevent word splitting
- Replaced A && B || C constructs with proper if-then-else
- Changed unused loop variable to _
- Added shellcheck directives for FreeBSD rc.d script
- Fixed ansible-lint risky-file-permissions warnings:
- Added explicit file permissions for sensitive files (mode 0600)
- Added permissions for config files and certificates (mode 0644)
- Set proper permissions for directories (mode 0755)
- Fixed yamllint compatibility with ansible-lint:
- Added required octal-values configuration
- Quoted all octal mode values to prevent YAML misinterpretation
- Added comments-indentation: false as required
All tests pass and functionality remains unchanged.
* Remove algo.egg-info from version control
This directory is generated by Python package tools (pip/setuptools) and
should not be tracked in git. It's already listed in .gitignore but was
accidentally committed. The directory contains build metadata that is
regenerated when the package is installed.
* Restructure privacy documentation for clarity
- Simplified FAQ entry to be concise with link to README for details
- Added comprehensive Privacy and Logging section to README
- Clarified what IS logged by default vs what is not
- Explained two separate privacy settings (strongswan_log_level and privacy_enhancements_enabled)
- Added clear debugging instructions (need to change both settings)
- Removed confusing language about "enabling additional features"
- Made documentation more natural and less AI-generated sounding
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Ubuntu 22.04 iptables deployment issues and simplify config.cfg
Issues fixed:
1. Added base 'iptables' package to batch installation list (was missing, only iptables-persistent was included)
2. Fixed alternatives configuration for Ubuntu 22.04+ - only configure main iptables/ip6tables alternatives, not save/restore (they're handled as slaves)
Config.cfg improvements:
- Reduced from 308 to 198 lines (35% reduction)
- Moved privacy settings above "Advanced users only" line for better accessibility
- Clarified algo_no_log is for Ansible output, not server privacy
- Simplified verbose comments throughout
- Moved experimental performance options to commented section at end
- Better organized into logical sections
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add privacy features to README and improve feature descriptions
- Added privacy-focused feature bullet highlighting minimal logging and privacy enhancements
- Simplified IKEv2 bullet (removed redundant platform list)
- Updated helper scripts description to be more comprehensive
- Specified Ubuntu 22.04 LTS and automatic security updates
- Made feature list more concise and accurate
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix logrotate duplicate entries error in privacy role
The privacy role was creating logrotate configs that duplicated the default
Ubuntu rsyslog logrotate rules, causing deployment failures with errors like
'duplicate log entry for /var/log/syslog'.
Changes:
- Disable default rsyslog logrotate config before applying privacy configs
- Consolidate system log rotation into single config file
- Add missingok flag to handle logs that may not exist on all systems
- Remove forced immediate rotation that was triggering the error
This ensures privacy-enhanced log rotation works without conflicts.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix 'history: not found' error in privacy role
The 'history -c' command was failing because history is a bash built-in
that doesn't exist in /bin/sh (Ubuntu's default shell for scripts).
Changes:
- Removed the 'Clear current session history' task since it's ineffective
in Ansible context (each task runs in a new shell)
- History files are already cleared by the existing file removal tasks
- Added explanatory comment about why session history clearing is omitted
This fixes the deployment failure while maintaining all effective history
clearing functionality.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix BPF JIT sysctl error in privacy role
The net.core.bpf_jit_enable sysctl parameter was failing on some systems
because BPF JIT support is not available in all kernel configurations.
Changes:
- Separated BPF JIT setting into its own task with ignore_errors
- Made BPF JIT disabling optional since it's not critical for privacy
- Added explanatory comments about kernel support variability
- Both runtime sysctl and persistent config now handle missing parameter
This allows deployments to succeed on systems without BPF JIT support
while still applying the setting where available.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>