D8.3 Secrets Management 🔐
Το πρόβλημα με τα env vars
# ❌ Κοινό αλλά ΛΑΘΟΣ:
docker run -e POSTGRES_PASSWORD=MySecret123 postgres
# Πρόβλημα 1: Εμφανίζεται σε docker inspect
docker inspect postgres | grep -A5 Env
# "Env": ["POSTGRES_PASSWORD=MySecret123"] ← ορατό!
# Πρόβλημα 2: Εμφανίζεται σε ps
ps aux | grep docker
# ... -e POSTGRES_PASSWORD=MySecret123 ... ← ορατό!
# Πρόβλημα 3: Μπαίνει σε logs
# Αν app κάνει log τα env vars → secret exposed!
Pattern 1: Ansible Vault + File mount (Συνίσταται)
Το ασφαλέστερο pattern για single-host deployments:
# group_vars/all/vault.yml (encrypted)
vault_postgres_pass: "StrongP@ssw0rd!"
vault_redis_pass: "RedisP@ssw0rd!"
vault_app_secret: "SuperSecretKey!"
tasks:
# ── Δημιουργία secrets directory (700) ────────
- name: Secrets directory
ansible.builtin.file:
path: /run/secrets
state: directory
owner: root
group: root
mode: '0700'
# ── Γράψιμο secrets ως αρχεία ─────────────────
- name: Postgres password secret
ansible.builtin.copy:
content: "{{ vault_postgres_pass }}"
dest: /run/secrets/postgres_password
owner: root
group: "999" # ← postgres GID
mode: '0640' # ← μόνο root + postgres group
no_log: true
- name: App secret key
ansible.builtin.copy:
content: "{{ vault_app_secret }}"
dest: /run/secrets/app_secret_key
owner: root
group: "1000"
mode: '0640'
no_log: true
# ── Mount secrets ως read-only files ──────────
- name: PostgreSQL με file secret
community.docker.docker_container:
name: postgres_db
image: postgres:15-alpine
state: started
restart_policy: unless-stopped
volumes:
- "/run/secrets/postgres_password:/run/secrets/postgres_password:ro"
env:
POSTGRES_PASSWORD_FILE: "/run/secrets/postgres_password"
# ↑ Το postgres image διαβάζει αυτό αντί για POSTGRES_PASSWORD
POSTGRES_USER: appuser
POSTGRES_DB: mydb
# no_log ΔΕΝ χρειάζεται (δεν υπάρχουν secrets στα env!)
💡 PostgreSQL, MySQL, Redis υποστηρίζουν
_FILEsuffix για env vars που διαβάζουν από αρχείο αντί για env:
POSTGRES_PASSWORD_FILE=/run/secrets/pg_passMYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_passREDIS_PASSWORD_FILE=/run/secrets/redis_pass(custom)
Pattern 2: tmpfs secrets (in-memory)
tasks:
# ── Secrets σε tmpfs (RAM, δεν γράφονται σε disk) ──
- name: tmpfs secrets directory
ansible.posix.mount:
src: tmpfs
path: /run/secrets
fstype: tmpfs
opts: "size=32m,mode=0700,noexec,nosuid,nodev"
state: mounted
- name: Write secrets to tmpfs
ansible.builtin.copy:
content: "{{ vault_postgres_pass }}"
dest: /run/secrets/postgres_password
mode: '0600'
no_log: true
Τι να ΑΠΟΦΕΥΓΕΙΣ
# ❌ Secrets σε plain env vars
- community.docker.docker_container:
name: postgres
env:
POSTGRES_PASSWORD: "MySecret123" # ← ΕΠΙΚΙΝΔΥΝΟ
# ❌ Secrets hardcoded στο playbook
vars:
db_pass: "MySecret123" # ← ΕΠΙΚΙΝΔΥΝΟ (git log!)
# ❌ no_log: false με secrets
- name: Something with secrets
community.docker.docker_container:
env:
SECRET: "{{ vault_secret }}"
# no_log: true ← ΛΕΙΠΕΙ!
# ✅ Σωστό
- name: Something with secrets
community.docker.docker_container:
env:
SECRET_FILE: "/run/secrets/mysecret" # ← file reference
no_log: true # ← πάντα για secrets!
Σύνοψη D8.3
Secrets Management
│
├── ❌ Αποφεύγουμε:
│ ├── Plaintext env vars
│ └── Hardcoded values στο playbook
│
├── ✅ Χρησιμοποιούμε:
│ ├── Ansible Vault → encrypted στο git
│ ├── File mounts → /run/secrets/
│ ├── _FILE env vars (postgres, mysql)
│ └── no_log: true σε κάθε task με secrets
│
└── Extras:
├── /run/secrets: mode 0700
├── Secret files: mode 0640
└── tmpfs για in-memory secrets