# Where Settings and Preferences Are Managed in the Amnezia-Client Codebase

> Discover where Amnezia-Client settings and preferences are managed. Explore the three-layer architecture, SecureAppSettingsRepository, SecureQSettings, and controller classes for detailed insights.

- Repository: [Amnezia VPN/amnezia-client](https://github.com/amnezia-vpn/amnezia-client)
- Tags: internals
- Published: 2026-07-29

---

**The amnezia-client application manages all user preferences through a centralized three-layer architecture centered on the `SecureAppSettingsRepository` class, which persists data via `SecureQSettings` while `SettingsController` and `SettingsUiController` handle business logic and UI bindings.**

The amnezia-vpn/amnezia-client repository implements a robust, layered approach to settings management that separates persistence, business logic, and presentation concerns. Understanding where settings are stored and how they flow through the system is essential for contributors and security researchers auditing the VPN client. All user-configurable options—from DNS servers to kill-switch states—flow through specific controller and repository classes defined in the client source tree.

## The Three-Layer Settings Architecture

### SecureAppSettingsRepository: The Core Persistence Layer

The **SecureAppSettingsRepository** class serves as the single source of truth for all persistent user preferences. Located in [`client/core/repositories/secureAppSettingsRepository.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/core/repositories/secureAppSettingsRepository.h) (and its corresponding `.cpp` implementation), this repository wraps a `SecureQSettings` instance—a thin abstraction over Qt’s native `QSettings` that adds encryption for sensitive values.

This layer exposes typed getter and setter methods for every configurable option. For example, DNS preferences are managed through `useAmneziaDns()` and `setUseAmneziaDns(bool)` (lines 30-32), while kill-switch status uses `isKillSwitchEnabled()` and `setKillSwitchEnabled(bool)` (lines 65-66). Language settings are handled via `getAppLanguage()` and `setAppLanguage(QLocale)` (lines 27-28), and auto-connect functionality uses `isAutoConnect()` and `setAutoConnect(bool)` (lines 70-71).

### SettingsController: The Business Logic Facade

Sitting between the repository and the UI, the **SettingsController** class in [`client/core/controllers/settingsController.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/core/controllers/settingsController.h) translates high-level actions into repository calls. It exposes Qt slots like `toggleAmneziaDns(bool)` and `toggleLogging(bool)` (implemented in [`settingsController.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/settingsController.cpp), lines 43-51 and 73-81) that validate and forward changes to `SecureAppSettingsRepository`.

The controller also emits signals such as `killSwitchEnabledChanged` (defined in [`settingsController.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/settingsController.cpp), lines 53-55) to notify the UI of state changes, enabling reactive updates without direct coupling to the persistence layer.

### SettingsUiController: The UI Binding Layer

The presentation layer resides in [`client/ui/controllers/settingsUiController.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/ui/controllers/settingsUiController.h), where **SettingsUiController** connects Qt widgets to the `SettingsController`. This class forwards user interactions—for example, when a user toggles a switch in the preferences dialog—and reflects state changes back to the interface through Qt’s signal/slot mechanism.

## Complete Data Flow from UI to Storage

When a user modifies a setting, data flows through four distinct layers:

1. **UI Widget** captures the interaction in `SettingsUiController`
2. **SettingsUiController** invokes the appropriate slot on `SettingsController`
3. **SettingsController** validates the request and calls `SecureAppSettingsRepository`
4. **SecureAppSettingsRepository** persists the value via `SecureQSettings` (defined in [`client/core/utils/secureQSettings.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/core/utils/secureQSettings.h))

Platform-specific build configurations for settings like autostart are handled in `cmake/platform_settings.cmake`, though these intersect with the repository layer at runtime.

## Key Settings Methods and File References

The following table maps specific preferences to their managing classes and source locations:

- **DNS Usage**: Managed by `SecureAppSettingsRepository` via `useAmneziaDns()` / `setUseAmneziaDns(bool)` in [`secureAppSettingsRepository.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/secureAppSettingsRepository.h) (lines 30-32)
- **Primary/Secondary DNS**: Same repository using `primaryDns()` / `setPrimaryDns(const QString&)` (lines 34-36)
- **Kill-Switch**: `isKillSwitchEnabled()` / `setKillSwitchEnabled(bool)` (lines 65-66)
- **Auto-Connect**: `isAutoConnect()` / `setAutoConnect(bool)` (lines 70-71)
- **Application Language**: `getAppLanguage()` / `setAppLanguage(QLocale)` (lines 27-28)
- **UI Toggles**: `SettingsController` forwards calls through `toggleAmneziaDns(bool)` and `toggleLogging(bool)` ([`settingsController.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/settingsController.cpp), lines 43-51, 73-81)

## Code Examples

The following examples demonstrate how to interact with the settings system programmatically:

```cpp
// Enable Amnezia DNS from anywhere in the code
SettingsController settingsCtrl(serversRepo, appSettingsRepo);
settingsCtrl.toggleAmneziaDns(true);   // stores the flag via SecureAppSettingsRepository

```

```cpp
// Read the current UI language
QLocale currentLang = settingsCtrl.getAppLanguage();   // forwards to repository

```

```cpp
// React to a change in the kill-switch state (Qt signal/slot)
connect(&settingsCtrl, &SettingsController::killSwitchEnabledChanged,
        [](){ qDebug() << "Kill-switch state changed!"; });

```

## Summary

- **SecureAppSettingsRepository** in `client/core/repositories/` is the ultimate authority for persisting all user preferences through `SecureQSettings`.
- **SettingsController** in `client/core/controllers/` provides a business-logic façade with signal/slot interfaces for the rest of the application.
- **SettingsUiController** in `client/ui/controllers/` binds Qt widgets to the controller layer, ensuring UI state remains synchronized with persistence.
- Sensitive data is encrypted via the `SecureQSettings` wrapper before reaching Qt’s native `QSettings` storage.

## Frequently Asked Questions

### What class actually writes settings to disk in amnezia-client?

The **SecureAppSettingsRepository** class handles all disk persistence. It wraps `SecureQSettings` (found in [`client/core/utils/secureQSettings.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/core/utils/secureQSettings.h)), which encrypts sensitive values before storing them via Qt’s `QSettings` mechanism.

### How does the UI layer communicate with the settings backend?

The UI uses **SettingsUiController** to capture widget interactions, which forwards calls to **SettingsController**. The controller then invokes methods on **SecureAppSettingsRepository**, ensuring the UI remains decoupled from direct storage operations.

### Where are kill-switch and DNS preferences defined in the source code?

These reside in [`client/core/repositories/secureAppSettingsRepository.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/core/repositories/secureAppSettingsRepository.h). Kill-switch state uses `isKillSwitchEnabled()` and `setKillSwitchEnabled(bool)` (lines 65-66), while DNS settings use `useAmneziaDns()` / `setUseAmneziaDns(bool)` (lines 30-32) and `primaryDns()` / `setPrimaryDns(const QString&)` (lines 34-36).

### Is SettingsController just a pass-through to SecureAppSettingsRepository?

No. While **SettingsController** forwards many calls to the repository, it adds validation logic and emits Qt signals (like `killSwitchEnabledChanged`) that enable reactive UI updates. It also handles higher-level operations such as `toggleLogging(bool)`, providing a clean API for the presentation layer.