Skip to content
Back to skills

Sops Setup

ASecurity

Set up SOPS + age encryption for sharing .env files securely across machines. Detects existing state, installs tools, generates age keys, creates .sops.yaml, and encrypts .env files as YAML (avoids SOPS dotenv bug #1435). Use when user mentions "sops setup", "encrypt env", "share secrets", "secure env files", "sops age setup", "env encryption", "setup sops", "share env across machines".

  • 21 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 28, 2026
ai-agentspythonbashgit

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned May 28, 2026

npx -y skills add joaquimscosta/arkhe-claude-plugins --skill sops-setup --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sops Setup?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Sops Setup
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/joaquimscosta-sops-setup/badge)](https://www.skillsdirectory.com/skills/joaquimscosta-sops-setup)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: sops-setup
description: >-
  Set up SOPS + age encryption for sharing .env files securely across machines.
  Detects existing state, installs tools, generates age keys, creates .sops.yaml,
  and encrypts .env files as YAML (avoids SOPS dotenv bug #1435). Use when user
  mentions "sops setup", "encrypt env", "share secrets", "secure env files",
  "sops age setup", "env encryption", "setup sops", "share env across machines".
disable-model-invocation: true
---

# SOPS + age Setup Wizard

Interactive setup for SOPS + age encryption. Detects current state and guides through configuration.

**Important**: This skill uses YAML format for encrypted files (not dotenv) because SOPS has a [known bug (#1435)](https://github.com/getsops/sops/issues/1435) where the dotenv store corrupts backslash and `\n` sequences on decrypt. A helper script handles dotenv↔YAML conversion transparently.

## Pre-flight

Run the detection script to understand current state:
```bash
python3 ${CLAUDE_SKILL_DIR}/scripts/detect_sops.py <project-root>
```

## Two-Phase Workflow

### Phase 1: Detect

1. **Run the detector** on the project root:
   ```bash
   python3 ${CLAUDE_SKILL_DIR}/scripts/detect_sops.py <project-root>
   ```

2. **Summarize findings** — show a status table:

   | Component | Status | Detail |
   |-----------|--------|--------|
   | sops binary | installed/missing | version, path |
   | age binary | installed/missing | version, path |
   | age key | exists/missing | public key (truncated) |
   | .sops.yaml | exists/missing | # of authorized keys |
   | .env files | N found | list of filenames |
   | encrypted files | N found | list of *.enc.yaml files |
   | .gitignore | ok/needs update | env ignored, enc.yaml not ignored |

### Phase 2: Configure

Walk through each missing component. Skip steps where detection shows everything is already configured.

1. **Install tools** (if `tools.sops.installed` or `tools.age.installed` is false):
   - Show install commands based on `os` field:
     - **macOS**: `brew install sops age`
     - **Linux**: Show download URLs for latest binaries from GitHub releases
   - After user confirms installation, re-run detector to verify

2. **Generate age key** (if `age_key.exists` is false):
   - Create directory: `mkdir -p ~/.config/sops/age`
   - Generate key: `age-keygen -o ~/.config/sops/age/keys.txt`
   - **Set permissions**: `chmod 600 ~/.config/sops/age/keys.txt`
   - Display the public key and tell user to **save it somewhere safe** (password manager, secure note)

3. **Generate backup key** (recommended):
   - Use `AskUserQuestion` — offer to create an offline backup key for disaster recovery
   - If yes:
     ```bash
     age-keygen 2>&1 | tee /dev/stderr | grep "public key:" | awk '{print $NF}'
     ```
     Display BOTH the public key AND the full output (which includes the private key).
     Tell user: **Copy the entire output (including the private key line starting with AGE-SECRET-KEY-) to a password manager or secure offline storage. This is your recovery key.**
   - The backup public key will be added to `.sops.yaml` alongside the machine key

4. **Create `.sops.yaml`** (if `project.sops_yaml.exists` is false):
   - Write `.sops.yaml` with machine key + backup key (if generated):
     ```yaml
     creation_rules:
       - path_regex: (^|/)\.env\.[^/]+\.enc\.yaml$
         age: >-
           <machine-public-key>,
           <backup-public-key>
     ```
   - If `.sops.yaml` already exists but is missing this machine's key, offer to add it

5. **Set up `.gitattributes`** for diff-friendly encrypted files:
   - Add to `.gitattributes`:
     ```
     *.enc.yaml diff=sopsdiffer
     ```
   - Configure git:
     ```bash
     git config diff.sopsdiffer.textconv "sops decrypt"
     ```
   - This makes `git diff` show decrypted content for encrypted files

6. **Update `.gitignore`** (if needed):
   - Ensure `.env*` patterns are ignored (secrets must not be committed in plaintext)
   - Ensure `*.enc.yaml` is NOT ignored (encrypted files should be committed)
   - Show proposed changes and confirm with user before writing

7. **Encrypt files** (if `project.env_files` is non-empty):
   - Use `AskUserQuestion` (multiSelect: true) — show detected `.env*` files
   - For each selected file, convert dotenv→YAML then encrypt:
     ```bash
     python3 ${CLAUDE_SKILL_DIR}/scripts/dotenv_yaml.py to-yaml <file> > <file>.enc.yaml.tmp
     sops --encrypt <file>.enc.yaml.tmp > <file>.enc.yaml
     rm <file>.enc.yaml.tmp
     ```
     Example: `.env.local` → `.env.local.enc.yaml`
   - Verify each encrypted file was created successfully

8. **Confirmation summary** — show table of all actions taken:
   ```
   | Step | Action | Result |
   |------|--------|--------|
   | Tools | sops 3.9.4, age 1.2.0 | installed |
   | Key | Machine key generated | age1abc...def |
   | Key | Backup key generated | age1xyz...uvw (save offline!) |
   | Permissions | chmod 600 keys.txt | done |
   | Config | .sops.yaml created | 2 keys authorized |
   | Git | .gitattributes updated | sopsdiffer configured |
   | Git | .gitignore updated | .env* ignored |
   | Encrypt | .env.local → .env.local.enc.yaml | done |

   ## Next Steps
   - Commit .sops.yaml, .gitattributes, and *.enc.yaml files to git
   - On another machine: clone, install sops+age, place age key, run /devtools:sops-decrypt
   - To add another machine: /devtools:sops-add-key
   - To encrypt after editing .env: /devtools:sops-encrypt
   - To decrypt after pulling: /devtools:sops-decrypt
   ```

## Key Rules

- **Never overwrite** existing files without asking. Always offer merge/replace/skip.
- **Detect first** — skip steps that are already configured.
- **Use `AskUserQuestion`** for every decision. Do not assume user preferences.
- **YAML format only** — never use `--input-type dotenv`. Use the dotenv_yaml.py helper for conversion.
- **chmod 600** on age key files immediately after creation.
- **Display public keys** after generation — user needs them for multi-machine setup.
- **Verify after each step** — re-run relevant checks to confirm success.

## References

- **Workflow**: See [WORKFLOW.md](WORKFLOW.md) for detailed per-step flows
- **Examples**: See [EXAMPLES.md](EXAMPLES.md) for example setup sessions
- **Troubleshooting**: See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for common issues
- **Detection Script**: See [scripts/detect_sops.py](scripts/detect_sops.py) for detection logic
- **Converter**: See [scripts/dotenv_yaml.py](scripts/dotenv_yaml.py) for dotenv↔YAML conversion
- **Best Practices**: See [references/sops-best-practices.md](references/sops-best-practices.md) for research

Files in this skill

  • EXAMPLES.md3.6 KB
  • SKILL.md6.5 KB
  • TROUBLESHOOTING.md5.1 KB
  • WORKFLOW.md6.4 KB
  • references/sops-best-practices.md27.2 KB
  • scripts/detect_sops.py6.3 KB
  • scripts/dotenv_yaml.py6.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.