- Added comprehensive step-by-step guide in README.md for Vault Transit auto-unseal setup. - Included Docker Swarm stack definition (docker-stack-vault.yml). - Added Vault configuration templates and bootstrap scripts. - Configured Gitea workflows for the VaultTest environment.
168 lines
7.5 KiB
YAML
168 lines
7.5 KiB
YAML
version: '3.8'
|
|
|
|
services:
|
|
# -------------------------------------------------------------------------
|
|
# 1. PRIMARY VAULT CLUSTER (3 NODES - RAFT HIGH AVAILABILITY)
|
|
# -------------------------------------------------------------------------
|
|
# before deloy
|
|
## echo "kendi_urettigin_guclu_token" | docker secret create transit_master_token -
|
|
# after deploy
|
|
## docker exec -it $(docker ps -q -f name=iklimco_vault.1) vault operator init
|
|
vault:
|
|
image: hashicorp/vault:2.0.1
|
|
cap_add:
|
|
- IPC_LOCK
|
|
# Overriding the default entrypoint to manipulate configuration strictly in RAM memory
|
|
entrypoint: ["sh", "-c"]
|
|
# 1. Reads the transit token from Docker Secret into RAM
|
|
# 2. Substitutes TRANSIT_TOKEN_PLACEHOLDER and HOSTNAME_PLACEHOLDER via sed entirely in RAM
|
|
# 3. Writes the resolved config to /dev/shm (RAM-backed tmpfs) — no secret ever touches disk
|
|
# 4. Purges token variable, then execs vault as PID 1 with the resolved config
|
|
command: >
|
|
"export MASTER_TOKEN=$$(cat /run/secrets/transit_master_token);
|
|
cat /vault/config/vault.json | sed \"s/TRANSIT_TOKEN_PLACEHOLDER/$$MASTER_TOKEN/g\" | sed \"s/HOSTNAME_PLACEHOLDER/$$HOSTNAME/g\" > /dev/shm/vault.json;
|
|
unset MASTER_TOKEN;
|
|
exec vault server -config=/dev/shm/vault.json"
|
|
networks:
|
|
iklimco-net:
|
|
aliases:
|
|
- vault.iklim.co
|
|
environment:
|
|
# NOTE: VAULT_LOCAL_API_ADDR is intentionally omitted.
|
|
# Vault automatically discovers its own container IP and port (8200) from the listener block below.
|
|
VAULT_ADDR: "https://127.0.0.1:8200"
|
|
# PHASE 1 (Bootstrap): Keep it "true" so Vault CLI can operate on self-signed/temporary certificates.
|
|
# PHASE 2 (Strict SSL): set this 'false' once you switch your configuration to v2.
|
|
VAULT_SKIP_VERIFY: "true"
|
|
volumes:
|
|
# Persistent volume for primary Raft storage
|
|
- vault-data-vl:/vault/file
|
|
# Persistent volume for audit and operational logs
|
|
- vault-logs-vl:/vault/logs
|
|
# Read-only mount of the host directory where the real wildcard certificates are managed
|
|
- /opt/iklimco/ssl:/vault/certs:ro
|
|
configs:
|
|
# PHASE 1: Deploy with 'vault_template_v1' (TLS validation skipped for easy initialization)
|
|
# PHASE 2: Update this source to 'vault_template_v2' to enforce strict wildcard SSL verification
|
|
- source: vault_template_v2
|
|
target: /vault/config/vault.json
|
|
mode: 0444
|
|
secrets:
|
|
- transit_master_token
|
|
deploy:
|
|
mode: replicated
|
|
replicas: 3
|
|
placement:
|
|
# High Availability rule: Ensures Vault nodes are strictly scheduled across different physical Swarm workers
|
|
max_replicas_per_node: 1
|
|
constraints:
|
|
- node.labels.type == service
|
|
restart_policy:
|
|
condition: any
|
|
delay: 5s
|
|
|
|
# -------------------------------------------------------------------------
|
|
# 2. AUTO-UNSEAL HELPER (1 NODE - PERSISTENT ON-PREMISE KMS)
|
|
# -------------------------------------------------------------------------
|
|
# BOOTSTRAP (first deploy only — run these steps in order):
|
|
# Step 1: echo "bootstrap" | docker secret create vault_transit_unseal_key -
|
|
# Step 2: docker stack deploy ... (transit starts sealed and uninitialized)
|
|
# Step 3: docker exec -it $(docker ps -q -f name=iklimco_vault-transit) \
|
|
# vault operator init -key-shares=1 -key-threshold=1
|
|
# -> note the Unseal Key and Root Token from the output
|
|
# Step 4: docker service update --secret-rm vault_transit_unseal_key iklimco_vault-transit
|
|
# docker secret rm vault_transit_unseal_key
|
|
# echo "<Unseal-Key>" | docker secret create vault_transit_unseal_key -
|
|
# docker service update --secret-add vault_transit_unseal_key iklimco_vault-transit
|
|
# Step 5: (exec into container) unseal, enable transit engine, create autounseal key,
|
|
# create a dedicated policy token, then update the transit_master_token secret:
|
|
# vault operator unseal <Unseal-Key>
|
|
# vault login <Root-Token>
|
|
# vault secrets enable transit
|
|
# vault write -f transit/keys/autounseal
|
|
# vault policy write autounseal - <<EOF
|
|
# path "transit/encrypt/autounseal" { capabilities = ["update"] }
|
|
# path "transit/decrypt/autounseal" { capabilities = ["update"] }
|
|
# EOF
|
|
# vault token create -policy=autounseal -period=768h -orphan
|
|
# -> docker secret rm transit_master_token
|
|
# -> echo "<policy-token>" | docker secret create transit_master_token -
|
|
# NORMAL OPERATION: auto-unseals on restart using vault_transit_unseal_key
|
|
# NODE PINNING (recommended): pin to one node to prevent volume data loss on rescheduling
|
|
# docker node update --label-add vault_transit=true <node-hostname>
|
|
vault-transit:
|
|
image: hashicorp/vault:2.0.1
|
|
cap_add:
|
|
- IPC_LOCK
|
|
entrypoint: ["sh", "-c"]
|
|
# 1. Starts vault in background with persistent file storage config
|
|
# 2. Registers SIGTERM/SIGINT trap so Docker stop triggers graceful vault shutdown
|
|
# 3. Polls vault status; exit 1 = not ready yet, exit 0/2 = vault is responding
|
|
# 4. Auto-unseals using vault_transit_unseal_key secret (no-op when uninitialized)
|
|
# 5. Waits for vault to exit and propagates its exit code to Docker
|
|
command: >
|
|
"vault server -config=/vault/config/transit.json &
|
|
VAULT_PID=$$!;
|
|
trap 'kill -TERM $$VAULT_PID; wait $$VAULT_PID' TERM INT;
|
|
export VAULT_ADDR='http://127.0.0.1:8200';
|
|
for i in 1 2 3 4 5 6 7 8 9 10; do vault status > /dev/null 2>&1; [ $$? -ne 1 ] && break; sleep 2; done;
|
|
vault operator unseal $$(cat /run/secrets/vault_transit_unseal_key) > /dev/null 2>&1 || true;
|
|
wait $$VAULT_PID"
|
|
networks:
|
|
- iklimco-net
|
|
secrets:
|
|
- vault_transit_unseal_key
|
|
volumes:
|
|
- vault-transit-data-vl:/vault/file
|
|
configs:
|
|
- source: vault_transit_config
|
|
target: /vault/config/transit.json
|
|
mode: 0444
|
|
deploy:
|
|
mode: replicated
|
|
replicas: 1
|
|
placement:
|
|
constraints:
|
|
- node.labels.type == service
|
|
- node.labels.vault_transit == true
|
|
restart_policy:
|
|
condition: any
|
|
delay: 5s
|
|
|
|
configs:
|
|
# =========================================================================
|
|
# CONFIG TEMPLATE PHASE 1: Bootstrap / Initial Discovery (No Verification)
|
|
# =========================================================================
|
|
vault_template_v1:
|
|
file: ./vault-template-v1.json
|
|
|
|
# =========================================================================
|
|
# CONFIG TEMPLATE PHASE 2: Production Safe (Strict Wildcard SSL Enforcement)
|
|
# =========================================================================
|
|
vault_template_v2:
|
|
file: ./vault-template-v2.json
|
|
|
|
# =========================================================================
|
|
# TRANSIT VAULT CONFIG: Persistent file storage, TLS disabled (internal only)
|
|
# =========================================================================
|
|
vault_transit_config:
|
|
file: ./vault-template-transit.json
|
|
|
|
volumes:
|
|
vault-data-vl:
|
|
vault-logs-vl:
|
|
vault-transit-data-vl:
|
|
|
|
secrets:
|
|
# Must be provisioned via 'docker secret create transit_master_token -' before deployment
|
|
transit_master_token:
|
|
external: true
|
|
# First deploy: echo "bootstrap" | docker secret create vault_transit_unseal_key -
|
|
# After init: replace with the real unseal key from 'vault operator init' output
|
|
vault_transit_unseal_key:
|
|
external: true
|
|
|
|
networks:
|
|
iklimco-net:
|
|
external: true
|