Parâmetros dinâmicos

Este documento explica como funciona a configuração da plataforma, os dois mecanismos em jogo, sua precedência e as armadilhas a serem observadas.


Visão geral: dois sistemas separados

Gitrust usa dois sistemas de configuração independentes:

Système Source Modifiable à chaud Visible dans l'UI admin
Configuration statique Fichier .env + variables d'environnement Non (restart requis) Non
Configuration dynamique Table app_settings (PostgreSQL) Oui (effet immédiat) Oui (/admin/settings)

Existe um caso híbrido para OAuth (banco de dados prioritário, .env em fallback).


1. Configuração estática (.env)

Princípio

Variáveis ​​de ambiente são carregadas uma vez na inicialização por dotenvy::dotenv() e armazenadas em estruturas Rust imutáveis. Eles nunca são lidos novamente após a inicialização.

Arquivos de referência

Fichier Rôle
.env.example Template documenté avec toutes les variables
.env Configuration locale (gitignore)
.env.production Configuration de déploiement
.env.test Configuration de tests

Carregando estruturas

Struct Variables concernées
GitrustConfig GIT_REPOS_BASE_PATH, SSH_PORT, SSH_LISTEN_ADDR, SSH_HOST_KEY_PATH, CI_*, IMPORT_*
AppConfig APP_NAME, APP_THEME, APP_DEBUG
AuthConfig JWT_SECRET, JWT_EXPIRATION_MINUTES, SESSION_*, RATE_LIMIT_*, COOKIE_*
EmailConfig SMTP_*, EMAIL_*, IMAP_*

Comportamento

  • Carregado em RustwardenApp::build() na inicialização
  • Armazenado em Arc<Config> compartilhado via estado axum
  • Alterar .env sem reiniciar não tem efeito
  • Essas variáveis ​​NÃO são exibidas na interface administrativa

Lista de variáveis ​​estáticas (não exaustiva)

DATABASE_URL, SERVER_HOST, SERVER_PORT, RUST_LOG,
SSH_HOST_KEY_PATH, SSH_PORT, SSH_LISTEN_ADDR, SSH_PUBLIC_HOST,
JWT_SECRET, JWT_EXPIRATION_MINUTES, JWT_ISSUER,
REFRESH_TOKEN_EXPIRATION_DAYS, REMEMBER_ME_EXPIRATION_DAYS,
SESSION_TIMEOUT_MINUTES, SESSION_BACKEND,
RATE_LIMIT_LOGIN_PER_MINUTE, RATE_LIMIT_REFRESH_PER_MINUTE,
RATE_LIMIT_GENERAL_PER_MINUTE,
APP_DEBUG, COOKIE_SECURE, COOKIE_SAME_SITE,
ADMIN_USERNAME, ADMIN_EMAIL, ADMIN_PASSWORD,
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROM,
EMAIL_BASE_URL, EMAIL_QUEUE_*,
APP_NAME, APP_THEME, DEFAULT_LOCALE,
GIT_REPOS_BASE_PATH,
CI_ENABLED, CI_MAX_CONCURRENT, CI_REMOTE_HOST, CI_WORKSPACE_PATH

2. Configuração dinâmica (tabela app_settings)

Princípio

As configurações dinâmicas são armazenadas no banco de dados PostgreSQL na tabela app_settings e lidas em cada solicitação via AppSettingsService. Eles podem ser modificados instantaneamente por um administrador na interface /admin/settings.

Diagrama de tabela

CREATE TABLE app_settings (
    id          UUID PRIMARY KEY,
    key         VARCHAR(100) UNIQUE NOT NULL,
    value       TEXT NOT NULL,
    description TEXT,
    updated_by  UUID REFERENCES users(id) ON DELETE SET NULL,
    updated_at  TIMESTAMPTZ NOT NULL
);

Inicialização na inicialização

Na inicialização, AppSettingsService::initialize_default_settings() cria as configurações padrão somente se elas ainda não existirem na base:

let existing = Self::get_setting(db, key).await?;
if existing.is_none() {
    // ... insert valeur par défaut
}

Consequência crítica: uma vez que uma configuração existe na base (criada na primeira inicialização ou modificada através da UI), ela nunca é substituída por uma reinicialização subsequente.

Lista de configurações dinâmicas e seus valores padrão

Clé Défaut Description
app_domain env::var("APP_DOMAIN") ou "localhost" Domaine de l'application
allow_registration false Autoriser l'inscription publique
validation_email_required true Exiger la validation email
audit_log_level INFO Niveau de log d'audit
audit_log_actions ["create","update","delete","reset_password"] Actions auditées
password_min_length 8 Longueur minimum mot de passe
password_require_uppercase false Exiger des majuscules
password_require_lowercase false Exiger des minuscules
password_require_digits false Exiger des chiffres
password_require_special false Exiger des caractères spéciaux
password_change_require_email true Confirmation email pour changement mdp
password_expiration_enabled false Activer l'expiration des mots de passe
password_expiration_days 0 Durée d'expiration (jours)
password_expiration_alert_enabled false Alerte email avant expiration
password_expiration_alert_days_before 7 Jours avant expiration pour alerter
oauth_enabled false Activer OAuth/SSO
oauth_google_enabled false Activer Google OAuth
oauth_github_enabled false Activer GitHub OAuth
oauth_discord_enabled false Activer Discord OAuth
oauth_microsoft_enabled false Activer Microsoft OAuth
oauth_redirect_base_url "" URL de base pour les callbacks OAuth
oauth_auto_register true Créer un compte auto au premier login OAuth
oauth_link_existing_account true Lier un compte OAuth à un utilisateur existant
oauth_{provider}_client_id "" Client ID du provider OAuth
oauth_{provider}_client_secret "" Client secret (chiffré AES-256-GCM en base)
oauth_microsoft_tenant "" Tenant Azure AD

3. Caso híbrido: OAuth

OAuth é o único subsistema que combina ambas as fontes. A lógica em OAuthConfig::load():

Pour chaque réglage OAuth :
  1. Chercher dans app_settings (DB)
     → si trouvé et non vide : utiliser cette valeur
  2. Sinon : fallback sur la variable d'environnement
     → si absente : utiliser la valeur par défaut codée en dur

Importante: OAuthConfig::load() é chamado na inicialização. O resultado é armazenado em um Arc e não é reproduzido dinamicamente. ENTÃO :

  • Alterar uma configuração do OAuth por meio da UI do administrador requer uma reinicialização para que OAuthConfig seja recarregado
  • O .env é apenas um substituto se o banco de dados não tiver valor

4. Precedência e comportamento de reinicialização

Configurações estáticas (somente .env)

Action Effet immédiat Après restart
Modifier .env Non Oui

Configurações dinâmicas (somente banco de dados)

Action Effet immédiat Après restart
Modifier via UI admin Oui Oui (valeur en DB persiste)
Modifier le .env Aucun effet Aucun effet

Configurações híbridas (OAuth)

Action Effet immédiat Après restart
Modifier via UI admin Non (OAuthConfig est en Arc) Oui (DB prime sur .env)
Modifier .env Non Seulement si aucune valeur en DB

5. Principal armadilha: variáveis ​​fantasmas .env

Certas variáveis ​​presentes em .env.example dão a ilusão de definir configurações que na realidade são gerenciadas pelo banco de dados:

Variable .env Réglage DB correspondant La variable .env est-elle lue ?
ALLOW_REGISTRATION=true allow_registration Non — valeur par défaut codée en dur ("false")
EMAIL_VALIDATION_REQUIRED=true validation_email_required Non — valeur par défaut codée en dur ("true")
OAUTH_ENABLED=true oauth_enabled Oui, mais seulement en fallback si la DB n'a pas de valeur

Para ALLOW_REGISTRATION e EMAIL_VALIDATION_REQUIRED:

  • A variável .env está documentada em .env.example mas nunca é acessada por initialize_default_settings()
  • O valor inicial é codificado no serviço
  • Somente o valor no banco de dados (modificável via /admin/settings) é autêntico

Para app_domain, esta é a única configuração dinâmica que lê .env como a semente inicial.


6. Diagrama de decisão

                    ┌─────────────────────────────┐
                    │  Quel type de réglage ?      │
                    └──────────┬──────────────────-┘
              ┌────────────────┼────────────────┐
              ▼                ▼                ▼
     Infrastructure       Fonctionnel        OAuth
     (port, JWT, SMTP)    (inscription,      (providers,
                          mots de passe)      secrets)
              │                │                │
              ▼                ▼                ▼
         .env seul        DB seule         DB + fallback .env
              │                │                │
              ▼                ▼                ▼
      Restart requis    Effet immédiat    Restart requis
                        via /admin/       (OAuthConfig en Arc)
                        settings

7. Guia para administradores

Alterar uma configuração de infraestrutura

Edite .env (ou .env.production) e reinicie o serviço:

# Éditer
vim .env

# Redémarrer
systemctl restart gitrust    # production
# ou Ctrl+C + cargo run      # dev

Alterar uma configuração funcional

Faça login como administrador, vá para /admin/settings, modifique o valor e clique em "Salvar". O efeito é imediato, não é necessário reiniciar.

Alterar uma configuração OAuth

Via /admin/settings, modifique os valores do OAuth e reinicie o serviço (a configuração do OAuth é carregada na memória na inicialização e não é relida dinamicamente).

Verifique o valor real de uma configuração

Para configurações dinâmicas, consulte o banco de dados diretamente:

SELECT key, value, updated_at, updated_by
FROM app_settings
WHERE key = 'allow_registration';

Para configurações estáticas, verifique os logs na inicialização (RUST_LOG=debug).


8. Guia para desenvolvedores

Adicione uma nova configuração dinâmica

  1. Adicione a tupla (key, default_value, description) em AppSettingsService::initialize_default_settings():

    ("ma_nouvelle_cle", "valeur_par_defaut", Some("Description pour l'UI admin")),
    

  2. Leia o valor no código através do serviço:

    // Boolean avec défaut
    let enabled = AppSettingsService::get_bool(&db, "ma_nouvelle_cle", false).await?;
    
    // String
    let val = AppSettingsService::get_setting(&db, "ma_nouvelle_cle").await?;
    

  3. O valor aparecerá automaticamente em /admin/settings.

Adicione uma nova configuração estática

  1. Adicione variável em .env.example com documentação completa
  2. Leia a variável na estrutura Config correspondente via env::var()
  3. O valor não estará visível na interface administrativa

Adicionar configuração híbrida (DB + fallback .env)

Siga o padrão OAuth em crates/rustwarden-core/src/config/oauth.rs:

let ma_valeur = match db_val("ma_cle").await {
    Some(v) => v,
    None => env::var("MA_CLE").unwrap_or_else(|_| "defaut".to_string()),
};