PSA/docs/security/secrets_management.md
Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

172 lines
5.3 KiB
Markdown

# Secrets Management
This document outlines how sensitive data is managed in the application using Docker secrets.
## Overview
Instead of storing sensitive data in environment variables or configuration files, we use Docker secrets to securely manage sensitive information. This approach provides several benefits:
- Secrets are stored securely on disk
- Secrets are only mounted in containers that need them
- Secrets are never exposed in container inspection or logs
- Secrets are mounted as files, providing a consistent interface across services
## Secret Files
All secrets are stored in the `secrets/` directory at the project root. Each secret is stored in its own file:
### Database Secrets
- `postgres_password` - PostgreSQL admin password (used by 'postgres' user for administration)
- `db_password_server` - Application user password (used by 'app_user' for RLS-controlled access)
- `db_password_hocuspocus` - Hocuspocus service password
### Redis Secrets
- `redis_password` - Redis password
### Email Secrets
- `email_password` - SMTP server password
### Security Secrets
- `crypto_key` - Encryption key for sensitive data
- `token_secret_key` - JWT signing key
- `nextauth_secret` - NextAuth.js secret key
### OAuth Secrets
- `google_oauth_client_id` - Google OAuth client ID
- `google_oauth_client_secret` - Google OAuth client secret
## Usage in Docker Compose
Secrets are defined in the `docker-compose.yaml` file under the `secrets` section and mounted to services that need them. For example:
```yaml
secrets:
postgres_password:
file: ./secrets/postgres_password
db_password_server:
file: ./secrets/db_password_server
services:
postgres:
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
secrets:
- postgres_password
server:
environment:
DB_USER_SERVER: app_user
volumes:
- type: bind
source: ./secrets/db_password_server
target: /run/secrets/db_password_server
read_only: true
```
## Accessing Secrets in Containers
Secrets are mounted at `/run/secrets/<secret_name>` inside containers. Services should read secrets from these mounted files rather than environment variables.
Example of reading a secret in Node.js:
```javascript
const fs = require('fs');
const dbPassword = fs.readFileSync('/run/secrets/db_password_server', 'utf8').trim();
```
## Database Authentication
The system uses a two-user database authentication model for security:
1. Admin User (postgres):
- Username: postgres
- Password: Stored in postgres_password secret
- Used for:
* Database administration
* Setup and migrations
* Schema changes
* Full database access
2. Application User (app_user):
- Username: app_user
- Password: Stored in db_password_server secret
- Used for:
* Application database access
* Limited access via RLS policies
* Regular database operations
- Security:
* Access controlled by Row Level Security (RLS)
* Cannot modify schema or bypass RLS
## Security Considerations
1. Never commit secret files to version control
2. Add secret files to .gitignore
3. Use different secrets for different environments
4. Rotate secrets periodically
5. Limit secret access to only the services that need them
6. Use strong, unique passwords for each secret
7. Ensure proper file permissions on secret files
8. Follow principle of least privilege:
- Use app_user for application access
- Reserve postgres user for administration only
## Setting Up Secrets
1. Create the `secrets/` directory
2. Create individual files for each secret:
```bash
# Use single quotes to avoid shell expansion of special characters in secret values.
# If a value contains a single quote ('), use a quoted heredoc instead:
# cat > secrets/email_password <<'EOF'
# your-secret-value
# EOF
# Database
echo 'your-secure-admin-password' > secrets/postgres_password
echo 'your-secure-app-password' > secrets/db_password_server
echo 'your-secure-hocuspocus-password' > secrets/db_password_hocuspocus
# Redis
echo 'your-secure-password' > secrets/redis_password
# Security
echo 'your-32-char-min-key' > secrets/crypto_key
echo 'your-32-char-min-key' > secrets/token_secret_key
echo 'your-32-char-min-key' > secrets/nextauth_secret
# Email & OAuth
echo 'your-email-password' > secrets/email_password
echo 'your-client-id' > secrets/google_oauth_client_id
echo 'your-client-secret' > secrets/google_oauth_client_secret
```
3. Set appropriate permissions:
```bash
chmod 600 secrets/*
```
4. Update docker-compose files to use secrets
5. Update application code to read from secret files
## Environment Variables
The `.env.example` file indicates which values are managed via Docker secrets. When setting up a new environment:
1. Copy `.env.example` to `.env`
2. Fill in non-sensitive values in `.env`
3. Create corresponding secret files for sensitive values
## Best Practices
1. Always use secrets for sensitive data, never environment variables
2. Read secrets from files at runtime, not during build
3. Use consistent naming across all components
4. Document any changes to secret management
5. Keep secret files secure and backed up
6. Implement proper secret rotation procedures
7. Monitor secret usage and access patterns
8. Follow the principle of least privilege:
- Use app_user for normal operations
- Limit postgres user access to administration
- Implement proper RLS policies