Security Hardening
Hardening checklist and guidance for production CoreCube deployments.
TLS / HTTPS
Required for production. The session cookie is only marked Secure when CoreCube is served over HTTPS. Security headers such as HSTS are not emitted by the application — set them at your TLS-terminating reverse proxy.
- Deploy a reverse proxy (nginx, Caddy, Traefik) in front of CoreCube for TLS termination
- Use a valid certificate (Let's Encrypt via Caddy is the simplest option)
- Minimum TLS 1.2; prefer TLS 1.3
- Caddy automatically manages TLS — see Reverse Proxy
Admin Console access restriction
Restrict admin console access to specific IP ranges at the reverse proxy level:
location /admin {
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
proxy_pass http://localhost:7400;
}
The /v1 API and /mcp endpoints should remain accessible — they authenticate via API keys.
Encryption key management
The encryption key protects all connector credentials and LLM API keys at rest.
CoreCube reads the key from the ENCRYPTION_KEY environment variable, which must be a 64-character hex string (256 bits). If ENCRYPTION_KEY is unset, it falls back to a key file at DATA_DIR/encryption.key; if that file is also missing, it auto-generates a key and writes it there with mode 0600.
ENCRYPTION_KEY_FILECoreCube does not expand a _FILE indirection variable. Pointing ENCRYPTION_KEY_FILE at a Docker/Kubernetes secret has no effect — the app sees no ENCRYPTION_KEY, silently auto-generates a throwaway key, and your existing credentials become permanently undecryptable on the next redeploy.
Best practices:
- Set
ENCRYPTION_KEYdirectly to a 64-character hex string (generate one withopenssl rand -hex 32). Source it into the environment from your secret manager. - Alternatively, pre-create
DATA_DIR/encryption.keycontaining the hex key with file permissions0600before the first start, and keep that file on the persistent data volume. - Back up the key separately from the data volume. Key loss makes all credentials permanently unreadable.
- Key rotation is a manual operation (decrypt with the old key, re-encrypt with the new one). There is no built-in rotation command.
# Provide the key via the environment, sourced from your secret manager
environment:
ENCRYPTION_KEY: ${ENCRYPTION_KEY} # 64-char hex, e.g. openssl rand -hex 32
Docker security
The CoreCube image runs the server as a non-root user and uses tini for signal handling. The remaining controls below (read_only, cap_drop) are not image defaults — you supply them in your Compose file.
| Control | Setting | Source |
|---|---|---|
| User | Non-root bun user — the entrypoint runs as root only to fix /data ownership, then drops to bun via su-exec | Image default |
| Signal handling | tini as init process (ENTRYPOINT) | Image default |
| Filesystem | Read-only root filesystem (read_only: true) | Operator-supplied (Compose) |
| Capabilities | Drop all capabilities (cap_drop: ALL) | Operator-supplied (Compose) |
| Data directory | Explicit writable volume for DATA_DIR | Operator-supplied (Compose) |
Add these to your Docker Compose service:
services:
corecube:
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp
volumes:
- corecube-data:/data
PostgreSQL security
- Enforce SSL: add
?sslmode=requiretoPGVECTOR_URL,PGVECTOR_APP_URL, andPGVECTOR_MAINTENANCE_URL. - Use a dedicated bootstrap/admin role for
PGVECTOR_URL; do not point it at the built-inpostgressuperuser in production. - Use the restricted
corecube_approle forPGVECTOR_APP_URL. Query/retrieval traffic uses this pool and is subject to RLS. - Use the restricted
corecube_maintenancerole forPGVECTOR_MAINTENANCE_URL. Background cleanup and repair jobs use this pool when they need cross-scope knowledge access. - Keep the bootstrap/admin, app, and maintenance pools separate so request-path traffic cannot bypass RLS policies or perform DDL.
postgresql://corecube:password@pgvector:5432/corecube?sslmode=require
postgresql://corecube_app:password@pgvector:5432/corecube?sslmode=require
postgresql://corecube_maintenance:password@pgvector:5432/corecube?sslmode=require
Network isolation
Keep PostgreSQL and CoreCube Inference on an internal Docker network — not exposed to the host:
networks:
internal:
internal: true
services:
corecube:
networks: [internal, default]
ports:
- '7400:7400' # Only CoreCube exposed
pgvector:
networks: [internal]
# No ports exposed
Default credential change
The default credentials (admin@example.com / changeme123) must be changed immediately after first login.
- Log in to the Admin Console
- Click your profile icon → Profile
- Update your email and password
- Navigate to Settings and update any remaining defaults
Password policy
CoreCube enforces a single rule: passwords must be at least 8 characters. No complexity requirement (uppercase, digit, or symbol) is applied. If you need stronger passwords, enforce them through your own operational policy.
API key hygiene
- Create separate API keys per client application — do not share keys
- Set an expiration date on keys that are used temporarily
- Revoke keys immediately when a client is decommissioned
- Use service keys for shared frontends (OpenWebUI) so per-user permissions apply
- Review key usage in Admin Console → API Keys → Usage
Session management
By default a session has a 30-day absolute lifetime and a 60-minute idle timeout. Activity extends the idle window but never the absolute lifetime. For higher-security environments, shorten both:
SESSION_MAX_LIFETIME_HOURS=8
SESSION_IDLE_TIMEOUT_MINUTES=30
Changing a user's password revokes that user's other sessions. A role change revokes sessions only when the role is downgraded to no_access. Admins can revoke a user's sessions from the Admin Console.
Audit log retention
Configure audit log retention in Admin Console → Settings → Audit:
- Default: 90 days
- Shorter retention reduces storage but limits forensic analysis
- Query text storage verbosity:
full,truncated, ordisabled(for privacy-sensitive environments)
Dependency updates
- All dependencies are pinned to exact versions in the lockfile
- Monitor the CoreCube GitHub releases for security updates
- Apply updates promptly:
docker compose pull && docker compose up -d
What v1 does not include
These controls are planned for future releases or EE:
| Control | Status |
|---|---|
| Backup encryption (AES-256-GCM) | Planned (Phase 6) |
| IP allowlists for admin/API | Planned |
| Multi-factor authentication | Planned (EE) |
| HSM key storage | Planned (EE) |
| Cryptographic audit log chaining | Planned (EE) |
Until backup encryption is available, store pg_dump backups on encrypted media.