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
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
172 lines
5.3 KiB
Markdown
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
|