一键导入
encrypt-secret
Create or update secrets using Infisical (preferred) or legacy agenix files
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create or update secrets using Infisical (preferred) or legacy agenix files
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | encrypt-secret |
| description | Create or update secrets using Infisical (preferred) or legacy agenix files |
| compatibility | Requires infisical CLI, agenix, agenix-helper |
| metadata | {"author":"ruinous.ai","version":"2.0","domain":"secrets"} |
| parameters | {"secret_name":{"type":"string","description":"Name of the secret (e.g., GITHUB_WEBHOOK_SECRET)","required":true,"placeholder":"MY_SECRET_NAME"},"secret_path":{"type":"string","description":"Infisical path (e.g., /shared, /services/openclaw, /hosts/chassis/openclaw)","required":true,"placeholder":"/shared"},"secret_value":{"type":"string","description":"The secret value (or 'generate' for random hex)","required":false,"placeholder":"generate"},"mode":{"type":"string","description":"infisical (default) or legacy","required":false,"default":"infisical"}} |
Create or update secrets using Infisical (preferred) or legacy agenix file encryption.
| Property | Value |
|---|---|
| Infisical API | https://infisical.meskill.farm |
| Project ID | f95d3144-22bb-4c95-9ee8-f3319d4924d5 |
| Environment | homelab |
If parameters are missing, use mcp_question to gather them:
mcp_question({
questions: [
{
question: "What type of secret are you creating?",
header: "Secret Type",
options: [
{ label: "Infisical (Recommended)", description: "Store in centralized Infisical, generate .age via mkGenerator" },
{ label: "Legacy agenix file", description: "Direct .age encryption for binary files (certs, keys)" }
]
}
]
})
For Infisical secrets, also ask:
mcp_question({
questions: [
{
question: "Is this secret used by multiple different services?",
header: "Secret Scope",
options: [
{ label: "Yes - shared across services", description: "Same value used by openclaw, n8n, opencode, etc. → /shared/" },
{ label: "No - one service only", description: "Dedicated to a single service → /services/ or /hosts/" }
]
}
]
})
// If service-specific, follow up:
mcp_question({
questions: [
{
question: "Is this secret the same across all hosts running this service?",
header: "Host Scope",
options: [
{ label: "Yes - service-wide", description: "Same on any host running the service → /services/<service>/" },
{ label: "No - host-specific", description: "Different per host instance → /hosts/<host>/<service>/" }
]
}
]
})
Then ask for the specific path components:
mcp_question({
questions: [
{
question: "What is the service name?",
header: "Service Name",
options: [
{ label: "openclaw", description: "OpenClaw/Moltbot AI assistant" },
{ label: "opencode", description: "OpenCode AI coding services" },
{ label: "budgey", description: "Budgey finance assistant" },
{ label: "caddy", description: "Caddy reverse proxy" },
{ label: "n8n", description: "n8n workflow automation" }
]
},
{
question: "What is the secret name?",
header: "Secret Name",
options: [] // Free text input
},
{
question: "How should the value be set?",
header: "Secret Value",
options: [
{ label: "Generate random (64 hex chars)", description: "openssl rand -hex 32" },
{ label: "Generate random (32 hex chars)", description: "openssl rand -hex 16" },
{ label: "Enter value manually", description: "You will provide the value" }
]
}
]
})
# Unlock agenix identity first (enter passphrase once per session)
just unlock
# Login to Infisical (interactive) if not already
infisical login --domain https://infisical.meskill.farm
# Or set token
export INFISICAL_TOKEN="your-token"
PROJECT_ID="f95d3144-22bb-4c95-9ee8-f3319d4924d5"
# Generate random value if needed
SECRET_VALUE=$(openssl rand -hex 32)
# Create the secret
infisical secrets set SECRET_NAME="$SECRET_VALUE" \
--env=homelab \
--path=/shared \
--projectId=$PROJECT_ID
Add to the appropriate host configuration:
# Enable Infisical integration (if not already)
ruinous.infisical.enable = true;
# Shared secret (used by multiple services)
age.secrets.<host>_<service>_<secret_name> = {
generator.script = config.ruinous.infisical.mkGenerator {
name = "GITHUB_TOKEN";
path = "/shared";
};
mode = "400";
};
# Service-specific secret (not host-specific)
age.secrets.<host>_openclaw_openai_key = {
generator.script = config.ruinous.infisical.mkGenerator {
name = "OPENAI_API_KEY";
path = "/services/openclaw";
};
mode = "400";
owner = "jmeskill";
};
# Host-specific secret
age.secrets.chassis_openclaw_discord_token = {
generator.script = config.ruinous.infisical.mkGenerator {
name = "DISCORD_TOKEN";
path = "/hosts/chassis/openclaw";
};
mode = "400";
owner = "jmeskill";
};
# Generate secrets from Infisical
agenix generate -a
# Rekey for all hosts
just rekey
# Stage the generated files
git add secrets/
# Check build passes
just check <host>
# Deploy changes
just deploy <host>
# View the secret (after deployment)
# cat /run/agenix/<secret_name>
/
├── shared/ # Cross-service secrets (same value everywhere)
│ ├── GITHUB_TOKEN
│ ├── ANTHROPIC_API_KEY
│ └── CLOUDFLARE_API_TOKEN
│
├── services/ # Service-specific, NOT host-specific
│ ├── openclaw/
│ │ └── OPENAI_API_KEY # OpenClaw's dedicated key
│ ├── budgey/
│ │ └── DATABASE_URL
│ └── opencode/
│ └── PROJECT_TOKEN
│
├── hosts/ # Host-specific service instances
│ ├── chassis/
│ │ ├── openclaw/
│ │ │ └── DISCORD_TOKEN
│ │ └── caddy/
│ │ └── BASIC_AUTH_HASH
│ ├── monolith/
│ │ └── ...
│ └── ...
│
└── nixos/ # LEGACY - being migrated
Is this secret used by multiple different services?
├─ YES → /shared/
└─ NO → Is this secret the same across all hosts running this service?
├─ YES → /services/<service>/
└─ NO → /hosts/<host>/<service>/
| Path | Purpose | Examples |
|---|---|---|
/shared/ | Same value used by MULTIPLE services | GITHUB_TOKEN, ANTHROPIC_API_KEY, CLOUDFLARE_API_TOKEN |
/services/<service>/ | Service-specific, any host | /services/openclaw/OPENAI_API_KEY, /services/budgey/DATABASE_URL |
/hosts/<host>/<service>/ | Host-specific instance | /hosts/chassis/openclaw/DISCORD_TOKEN |
Use /shared/ | Use /services/<service>/ | Use /hosts/<host>/<service>/ |
|---|---|---|
| Same API account for all | Isolated quota/billing per service | Different per host instance |
| GITHUB_TOKEN for all tools | Service needs own rate limits | Discord bot per host |
| Shared Cloudflare account | Rotate independently | Host-specific auth |
PROJECT_ID="f95d3144-22bb-4c95-9ee8-f3319d4924d5"
# List secrets at path
infisical secrets --env=homelab --path=/shared --projectId=$PROJECT_ID
# Get single secret value
infisical secrets get SECRET_NAME --env=homelab --path=/shared \
--projectId=$PROJECT_ID --plain
# Update existing secret
infisical secrets set SECRET_NAME="new-value" --env=homelab --path=/shared \
--projectId=$PROJECT_ID
# Delete secret
infisical secrets delete SECRET_NAME --env=homelab --path=/shared \
--projectId=$PROJECT_ID
# Create folder
infisical secrets folders create --name=newfolder --env=homelab --path=/ \
--projectId=$PROJECT_ID
Infisical supports references to avoid duplication:
# Create alias in same path
infisical secrets set 'GITHUB_ACCESS_TOKEN=${GITHUB_TOKEN}' \
--env=homelab --path=/shared --projectId=$PROJECT_ID
# Reference /shared secret from a service path
infisical secrets set 'ANTHROPIC_API_KEY=${shared.ANTHROPIC_API_KEY}' \
--env=homelab --path=/services/openclaw --projectId=$PROJECT_ID
# Reference /shared secret from a host-specific path
infisical secrets set 'GITHUB_TOKEN=${shared.GITHUB_TOKEN}' \
--env=homelab --path=/hosts/chassis/openclaw --projectId=$PROJECT_ID
Use for binary files (certificates, SSH keys) that can't be stored as text in Infisical.
# Unlock agenix identity
just unlock
Create directory structure:
mkdir -p hosts/<hostname>/files/docker/env
Create plaintext content:
cat > /tmp/secret.txt << 'EOF'
SECRET_KEY=value
API_TOKEN=value
EOF
Encrypt the file:
just encrypt <output-path>.age
# Or with input file:
agenix edit -i /tmp/secret.txt <output-path>.age
Clean up and rekey:
rm /tmp/secret.txt
just rekey
age.secrets.<hostname>_<service>_<name> = {
rekeyFile = ./files/docker/env/<service>.env.age;
mode = "600";
};
| Purpose | Path Pattern |
|---|---|
| Docker env | hosts/<host>/files/docker/env/<service>.env.age |
| Caddyfiles | hosts/<host>/files/caddy/Caddyfile.age |
| Cloudflared certs | hosts/<host>/files/cloudflared/cert.pem.age |
| Cloudflared tunnels | hosts/<host>/files/cloudflared/<tunnel>.json.age |
| Use Infisical When | Use Legacy When |
|---|---|
| Text-based secrets (tokens, passwords, API keys) | Binary files (certificates, SSH keys) |
| Secrets shared across hosts | Host-specific file structures |
| Secrets that change frequently | Static credentials |
| Secrets you want to manage via UI | Secrets tightly coupled to file paths |
# 1. Unlock agenix identity
just unlock
# 2. Generate and store in Infisical
PROJECT_ID="f95d3144-22bb-4c95-9ee8-f3319d4924d5"
WEBHOOK_SECRET=$(openssl rand -hex 32)
infisical secrets set GITHUB_FORGE_WEBHOOK_SECRET="$WEBHOOK_SECRET" \
--env=homelab --path=/shared --projectId=$PROJECT_ID
# 3. Add to Nix config (e.g., hosts/monolith/webhooks.nix)
# age.secrets.monolith_github_webhook_secret = {
# generator.script = config.ruinous.infisical.mkGenerator {
# name = "GITHUB_FORGE_WEBHOOK_SECRET";
# path = "/shared";
# };
# mode = "400";
# };
# 4. Generate and rekey
agenix generate -a
just rekey
git add secrets/
# 5. Verify and deploy
just check monolith
just deploy monolith
just unlock before startingmkGenerator with correct name/pathagenix generate -ajust rekeygit add secrets/)just check <host>)just deploy <host>)just unlock before startingjust rekeyage.secrets.* entry to Nix configagenix-helper lock when doneAdd an AeroSpace window rule to assign an app/window to a workspace (macOS only)
Re-encrypt all secrets after modifying .age files or changing host keys
Decrypt and view the contents of an .age secret file
Deploy NixOS/Darwin configuration to local or remote host using justfile commands
Analyze project from URL/path and auto-detect build system to create Nix package
Add a new project to ruinage with DNS, Caddy, Gatus, and deployment