diff --git a/website/src/app/docs/migration/page.tsx b/website/src/app/docs/migration/page.tsx
new file mode 100644
index 0000000..799af4c
--- /dev/null
+++ b/website/src/app/docs/migration/page.tsx
@@ -0,0 +1,251 @@
+import { CodeBlock } from "@/components/CodeBlock";
+import { Section, PageHeader } from "@/components/DocsComponents";
+
+export const metadata = {
+ title: "Migration Guides - xenvsync",
+ description: "Step-by-step guides to migrate from dotenv-vault, sops, and git-crypt to xenvsync.",
+ openGraph: {
+ title: "Migration Guides - xenvsync",
+ description: "Migrate from dotenv-vault, sops, or git-crypt to xenvsync with step-by-step instructions.",
+ url: "https://xenvsync.softexforge.io/docs/migration",
+ },
+ alternates: { canonical: "https://xenvsync.softexforge.io/docs/migration" },
+};
+
+export default function Migration() {
+ return (
+
+
+
+ {/* dotenv-vault */}
+
+
+ dotenv-vault uses a cloud service to manage encrypted vaults. xenvsync does everything locally with no cloud dependency.
+
+
+ 1. Export your secrets
+
+ If you have a .env.vault from dotenv-vault, you need to decrypt it first using your DOTENV_KEY:
+
+
+{`# Decrypt your dotenv-vault secrets to a plain .env file
+# (use your dotenv-vault tooling or dashboard to export)
+npx dotenv-vault@latest pull
+
+# Verify your .env has all expected variables
+cat .env`}
+
+
+ 2. Set up xenvsync
+
+{`# Initialize xenvsync (generates encryption key)
+xenvsync init
+
+# Encrypt your .env
+xenvsync push
+
+# Verify the vault
+xenvsync verify`}
+
+
+ 3. Clean up dotenv-vault
+
+{`# Remove dotenv-vault artifacts
+rm -f .env.vault # (the old dotenv-vault format, now replaced by xenvsync's)
+rm -f .env.keys
+
+# Remove dotenv-vault from dependencies
+npm uninstall dotenv-vault
+
+# Commit the new vault
+git add .env.vault .gitignore
+git commit -m "Migrate from dotenv-vault to xenvsync"`}
+
+
+ 4. Verify
+
+{`# Delete .env and restore from vault
+rm .env
+xenvsync pull
+cat .env # should match your original secrets
+
+# Test in-memory injection
+xenvsync run -- env | grep YOUR_KEY`}
+
+
+
+ Key differences: xenvsync vaults are not compatible with dotenv-vault vaults. The .env.vault file format is different.
+ xenvsync uses AES-256-GCM with a local key, while dotenv-vault uses a cloud-managed key.
+
+
+
+ {/* sops */}
+
+
+ sops encrypts individual values within YAML/JSON/ENV files. xenvsync encrypts the entire .env file as a single unit.
+
+
+ 1. Export your secrets
+
+{`# Decrypt your sops-encrypted file to plain .env
+sops -d secrets.enc.env > .env
+
+# Or from YAML/JSON:
+sops -d secrets.yaml | yq -r 'to_entries[] | "\\(.key)=\\(.value)"' > .env`}
+
+
+ 2. Set up xenvsync
+
+{`# Initialize xenvsync
+xenvsync init
+
+# Encrypt your .env
+xenvsync push
+
+# Verify
+xenvsync diff # should show no differences`}
+
+
+ 3. Clean up sops
+
+{`# Remove sops-encrypted files
+rm -f secrets.enc.env secrets.yaml
+rm -f .sops.yaml
+
+# Update .gitignore if needed
+# (xenvsync init already added .xenvsync.key and .env)
+
+# Commit
+git add .env.vault .gitignore
+git rm secrets.enc.env .sops.yaml # if tracked
+git commit -m "Migrate from sops to xenvsync"`}
+
+
+ 4. Verify
+
+{`rm .env
+xenvsync pull
+xenvsync verify`}
+
+
+
+ Key differences: sops supports KMS, PGP, and age keys with per-value encryption. xenvsync uses a single AES-256-GCM key (or X25519 team keys) and encrypts the entire file.
+ If you need per-value encryption or cloud KMS integration, sops may be a better fit.
+
+
+
+ {/* git-crypt */}
+
+
+ git-crypt transparently encrypts files in a Git repo. xenvsync uses explicit push/pull commands and encrypts only .env files.
+
+
+ 1. Export your secrets
+
+{`# Ensure your repo is unlocked (files are decrypted in working tree)
+git-crypt unlock
+
+# Copy your .env (it's already in plaintext when unlocked)
+cp .env .env.backup
+
+# Verify contents
+cat .env`}
+
+
+ 2. Remove git-crypt
+
+{`# Lock first to see what was encrypted
+git-crypt lock
+
+# Remove git-crypt configuration
+rm -rf .git-crypt/
+rm -f .gitattributes # or remove git-crypt filter lines
+
+# Unlock to restore plaintext
+git-crypt unlock`}
+
+
+ 3. Set up xenvsync
+
+{`# Initialize xenvsync
+xenvsync init
+
+# Restore .env if needed
+cp .env.backup .env
+
+# Encrypt
+xenvsync push
+
+# Verify
+xenvsync verify`}
+
+
+ 4. Commit the migration
+
+{`git add .env.vault .gitignore
+git commit -m "Migrate from git-crypt to xenvsync"
+
+# Clean up backup
+rm .env.backup`}
+
+
+
+ Key differences: git-crypt encrypts transparently on git operations and works with any file type.
+ xenvsync is focused specifically on .env files and adds features like in-memory injection (run), multi-environment support, and vault diff/status.
+
+
+
+ {/* Team migration */}
+
+
+ If your team uses xenvsync's V2 (team) mode, follow these additional steps after any migration:
+
+
+{`# Each team member generates their keypair (once)
+xenvsync keygen
+
+# Share public keys and add to roster
+xenvsync team add alice
+xenvsync team add bob
+
+# Re-push to create V2 vault with per-member encryption
+xenvsync push
+
+# Commit the roster and vault
+git add .xenvsync-team.json .env.vault
+git commit -m "Enable V2 team vault"`}
+
+
+
+ {/* Comparison */}
+
+
+
+
+
+ | Feature |
+ xenvsync |
+ dotenv-vault |
+ sops |
+ git-crypt |
+
+
+
+ | No cloud required | Yes | No | Yes | Yes |
+ | In-memory injection | Yes | No | No | No |
+ | Multi-environment | Yes | Yes | Manual | No |
+ | Team sharing | X25519 | Cloud | KMS/PGP | GPG |
+ | Key rotation | Yes | Cloud | Manual | No |
+ | Diff / audit log | Yes | No | Partial | No |
+ | Single binary | Yes | No | Yes | No |
+ | Passphrase protection | Yes | No | No | No |
+
+
+
+
+
+ );
+}
diff --git a/website/src/components/Search.tsx b/website/src/components/Search.tsx
index 1a71abe..48c84ca 100644
--- a/website/src/components/Search.tsx
+++ b/website/src/components/Search.tsx
@@ -279,6 +279,44 @@ const searchIndex: SearchEntry[] = [
"version prints version commit hash and build date. Build info is injected at compile time via ldflags.",
},
+ // Migration Guides
+ {
+ href: "/docs/migration",
+ title: "Migration Guides",
+ section: "Docs",
+ heading: "From dotenv-vault",
+ keywords: ["migration", "dotenv-vault", "switch", "migrate", "cloud", "DOTENV_KEY"],
+ content:
+ "Step-by-step guide to migrate from dotenv-vault to xenvsync. Export secrets from dotenv-vault, set up xenvsync, and verify the migration. No cloud dependency needed.",
+ },
+ {
+ href: "/docs/migration",
+ title: "Migration Guides",
+ section: "Docs",
+ heading: "From sops",
+ keywords: ["migration", "sops", "switch", "migrate", "kms", "pgp", "age", "yaml"],
+ content:
+ "Step-by-step guide to migrate from sops to xenvsync. Decrypt sops files, set up xenvsync encryption, and clean up sops configuration.",
+ },
+ {
+ href: "/docs/migration",
+ title: "Migration Guides",
+ section: "Docs",
+ heading: "From git-crypt",
+ keywords: ["migration", "git-crypt", "switch", "migrate", "gpg", "transparent"],
+ content:
+ "Step-by-step guide to migrate from git-crypt to xenvsync. Export decrypted files, remove git-crypt configuration, and set up xenvsync.",
+ },
+ {
+ href: "/docs/migration",
+ title: "Migration Guides",
+ section: "Docs",
+ heading: "Feature Comparison",
+ keywords: ["comparison", "compare", "vs", "alternative", "dotenv-vault", "sops", "git-crypt"],
+ content:
+ "Feature comparison table between xenvsync, dotenv-vault, sops, and git-crypt. Covers cloud dependency, in-memory injection, multi-environment, team sharing, key rotation, and more.",
+ },
+
// Security
{
href: "/docs/security",
diff --git a/website/src/components/Sidebar.tsx b/website/src/components/Sidebar.tsx
index 351516e..2d175ac 100644
--- a/website/src/components/Sidebar.tsx
+++ b/website/src/components/Sidebar.tsx
@@ -13,11 +13,13 @@ import {
Menu,
X,
ChevronRight,
+ ArrowRightLeft,
} from "lucide-react";
export const docPages = [
{ href: "/docs/getting-started", label: "Getting Started", icon: BookOpen, section: "Learn" },
{ href: "/docs/installation", label: "Installation", icon: Download, section: "Learn" },
+ { href: "/docs/migration", label: "Migration Guides", icon: ArrowRightLeft, section: "Learn" },
{ href: "/docs/commands", label: "Commands", icon: Terminal, section: "Reference" },
{ href: "/docs/security", label: "Security Model", icon: Shield, section: "Reference" },
{ href: "/roadmap", label: "Roadmap", icon: Map, section: "Project" },