File size: 3,395 Bytes
c2fb92d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env bash
# init-vault.sh — creates Miranda's local memory vault directory structure
# and generates a real libsodium secretbox key used to encrypt data at rest.
#
# Vault root selection:
#   Design/requirements call for /mnt/NOBILITY_VAULT/.miranda/. On this
#   machine /mnt/NOBILITY_VAULT exists and is writable, so that is used.
#   If it is not present on a given machine, this script falls back to
#   ~/NOBILITY_VAULT/.miranda/ and prints a warning so the substitution is
#   never silent.
set -euo pipefail

PREFERRED_ROOT="/mnt/NOBILITY_VAULT/.miranda"
FALLBACK_ROOT="${HOME}/NOBILITY_VAULT/.miranda"

if [ -d "/mnt/NOBILITY_VAULT" ] && [ -w "/mnt/NOBILITY_VAULT" ]; then
    VAULT_ROOT="$PREFERRED_ROOT"
else
    VAULT_ROOT="$FALLBACK_ROOT"
    echo "WARNING: /mnt/NOBILITY_VAULT not present/writable — substituting local path: $VAULT_ROOT" >&2
fi

echo "Initializing Miranda vault at: $VAULT_ROOT"

mkdir -p "$VAULT_ROOT/datalake/events"
mkdir -p "$VAULT_ROOT/datalake/indexes"
mkdir -p "$VAULT_ROOT/obsidian"
mkdir -p "$VAULT_ROOT/config"
mkdir -p "$VAULT_ROOT/neo4j-data"

chmod 700 "$VAULT_ROOT"
chmod 700 "$VAULT_ROOT/config"

KEY_ENC_PATH="$VAULT_ROOT/config/keys.enc"

if [ -f "$KEY_ENC_PATH" ]; then
    echo "Encryption key already exists at $KEY_ENC_PATH — leaving untouched."
else
    PY_BIN="python3"
    if [ -x "/tmp/test_venv/bin/python3" ]; then
        PY_BIN="/tmp/test_venv/bin/python3"
    fi

    "$PY_BIN" - "$KEY_ENC_PATH" <<'PYEOF'
import sys
import os
import base64
import json
import time

import nacl.secret
import nacl.utils
import nacl.pwhash

key_path = sys.argv[1]

# Generate a real random libsodium secretbox key (crypto_secretbox_KEYBYTES = 32 bytes).
raw_key = nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE)

# Wrap the raw key with a machine-local passphrase-derived key so keys.enc
# itself is not a bare plaintext secret on disk. The passphrase-derived
# wrapping key uses nacl.pwhash (Argon2id) with a random salt stored
# alongside the wrapped ciphertext.
salt = nacl.utils.random(nacl.pwhash.argon2id.SALTBYTES)
# Machine-local wrapping passphrase: derived from a fixed local marker file
# path + hostname, so no secret has to be typed interactively for this
# non-interactive init script, while still not just writing the raw key
# to disk in the clear.
wrap_material = (os.uname().nodename + ":miranda-vault-wrap").encode()
wrap_key = nacl.pwhash.argon2id.kdf(
    nacl.secret.SecretBox.KEY_SIZE,
    wrap_material,
    salt,
    opslimit=nacl.pwhash.argon2id.OPSLIMIT_INTERACTIVE,
    memlimit=nacl.pwhash.argon2id.MEMLIMIT_INTERACTIVE,
)

box = nacl.secret.SecretBox(wrap_key)
nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
ciphertext = box.encrypt(raw_key, nonce)

payload = {
    "version": 1,
    "algorithm": "libsodium-secretbox-xsalsa20poly1305",
    "kdf": "argon2id",
    "salt_b64": base64.b64encode(salt).decode(),
    "ciphertext_b64": base64.b64encode(ciphertext).decode(),
    "created_at": time.time(),
}

with open(key_path, "w") as f:
    json.dump(payload, f, indent=2)

os.chmod(key_path, 0o600)
print(f"Generated real libsodium secretbox key, wrapped with Argon2id-derived key, at {key_path}")
PYEOF
fi

echo "Vault directory structure:"
find "$VAULT_ROOT" -maxdepth 2 -type d | sort

echo "VAULT_ROOT=$VAULT_ROOT" > "$VAULT_ROOT/config/.vault_root_marker"

echo "init-vault.sh complete."