## ADDED Requirements ### Requirement: Snell binary is installed The snell role SHALL download and install the Snell server binary from official release artifacts to `/usr/local/bin/snell-server`. The version SHALL be configurable via `snell_version`. #### Scenario: Fresh installation - **WHEN** the snell role runs on a server without Snell installed - **THEN** the specified version of the Snell binary is downloaded and installed - **THEN** the binary is executable #### Scenario: Version upgrade - **WHEN** `snell_version` is changed and the playbook is re-run - **THEN** the binary is replaced with the new version - **THEN** the Snell service is restarted ### Requirement: Snell configuration is templated The snell role SHALL generate a configuration file at `/etc/snell/snell-server.conf` from a Jinja2 template. The configuration SHALL include: `listen` address, `psk` (pre-shared key), and `ipv6` setting. #### Scenario: Configuration is generated from template - **WHEN** the snell role runs - **THEN** the config file is rendered with listen address, PSK, and ipv6 setting - **THEN** the config file permissions are restricted (readable only by root or snell service user) #### Scenario: Configuration change triggers restart - **WHEN** a snell variable is changed and the playbook is re-run - **THEN** the configuration file is updated - **THEN** the Snell service is restarted via handler ### Requirement: Snell runs as a systemd service The snell role SHALL create a systemd unit file for Snell and ensure it is enabled and started. #### Scenario: Service is running - **WHEN** the snell role completes - **THEN** the Snell systemd service is enabled and running - **THEN** the service runs under a dedicated non-root user ### Requirement: Snell port is allowed through UFW The snell role SHALL allow the Snell listen port through UFW. #### Scenario: Firewall allows Snell port - **WHEN** the snell role runs with `snell_port: 61080` - **THEN** UFW allows incoming TCP traffic on port 61080 ### Requirement: Snell PSK is auto-generated and persisted The snell role SHALL default the pre-shared key to an auto-generated value from `credentials/snell_psk`, with manual override supported via `snell_psk` variable. #### Scenario: PSK uses auto-generated default - **WHEN** the snell role runs without manual override - **THEN** the PSK comes from `credentials/snell_psk` lookup value - **THEN** if the credential file does not exist, a new 32-character random value is generated and saved