## ADDED Requirements ### Requirement: shadowsocks-rust is installed on the relay server The shadowsocks role SHALL download and install the shadowsocks-rust `ssserver` binary from GitHub releases to a configurable path, with a configurable version. #### Scenario: Fresh installation - **WHEN** the shadowsocks role runs on a relay server without shadowsocks-rust installed - **THEN** the specified version of `ssserver` binary is downloaded and installed - **THEN** the binary is executable and owned by a dedicated service user #### Scenario: Version upgrade - **WHEN** the shadowsocks version variable is changed and the playbook is re-run - **THEN** the binary is replaced with the new version - **THEN** the service is restarted ### Requirement: shadowsocks-rust runs as a systemd service The shadowsocks role SHALL create a systemd unit file for `ssserver` and ensure it is enabled and started. #### Scenario: Service is running - **WHEN** the shadowsocks role completes - **THEN** the `ssserver` systemd service is enabled and running - **THEN** the service runs under a dedicated non-root user ### Requirement: shadowsocks-rust configuration is templated The relay server's shadowsocks configuration SHALL be generated from a Jinja2 template with variables for port, password, and cipher method. #### Scenario: Configuration is generated from template - **WHEN** the shadowsocks role runs - **THEN** a JSON config file is rendered from template with port, password, and encryption method - **THEN** the config file permissions are restricted (readable only by the service user) #### Scenario: Configuration change triggers restart - **WHEN** a variable in `group_vars/relay.yml` is changed and the playbook is re-run - **THEN** the configuration file is updated - **THEN** the ssserver service is restarted ### Requirement: shadowsocks uses AEAD cipher The shadowsocks configuration SHALL use an AEAD cipher (e.g., `aes-256-gcm` or `chacha20-ietf-poly1305`), configurable via Ansible variable. The SS port and password SHALL default to auto-generated values from the `credentials/` directory, with manual override supported. #### Scenario: AEAD cipher is configured - **WHEN** the shadowsocks configuration is generated - **THEN** the `method` field uses the configured AEAD cipher - **THEN** the default cipher is `aes-256-gcm` if not overridden #### Scenario: Port and password use auto-generated defaults - **WHEN** the shadowsocks role runs without manual overrides - **THEN** the port and password come from `credentials/` lookup values ### Requirement: shadowsocks credentials are auto-generated and persisted The relay server's shadowsocks password and port SHALL be auto-generated on first run via Ansible `password` lookup and persisted in `credentials/`. Manual override via `--extra-vars` is supported. #### Scenario: Credentials are auto-generated - **WHEN** the playbook runs for the first time - **THEN** a random password and port are generated and persisted to `credentials/` - **THEN** no plaintext password exists in version-controlled files