↓ Lewati ke konten utama

Sinkronisasi File .env yang Aman dengan SOPS dan age

Zarvelion Zynji
Penulis
Zarvelion Zynji
Tech enthusiasts (self-proclaimed). Gaming addict (diagnosed). Anime simp (no regrets). I turn my hyperfixations into content—welcome to the chaos.
Daftar isi

Saya kerja pakai dua device utama: PC dan laptop. Biar nggak burnout kerja di rumah terus, kadang saya kerja dari coffee shop — suasana baru, niat produktif, tapi begitu project butuh fitur baru yang memakai key atau data sensitif… stuck. Key-key itu kan random string yang mustahil dihafal manusia normal, dan variable-nya numpuk di .env. Seringnya sih lupa update .env di laptop, baru ketahuan pas aplikasi error di tengah jalan.

Solusinya: sinkronkan .env secara aman antar device. Bukan dikirim lewat WhatsApp atau Discord (jangan pernah!), tapi di-encrypt dulu, di-commit ke git, lalu di-decrypt di device tujuan. Tools-nya: SOPS dan age.

Note

Artikel ini fokus Windows (winget + PowerShell), tapi tetap saya sertakan perintah untuk macOS/Linux karena workflow-nya lintas OS.


Apa itu SOPS dan age?
#

SOPS (Secrets OPerationS, buatan Mozilla) adalah tool untuk mengenkripsi file secrets — tapi bukan satu file jadi satu blob, melainkan hanya nilai (value)-nya saja yang dienkripsi, dan dia paham format file (JSON, YAML, INI, dotenv). Jadi struktur file tetap kebaca, cuma isinya yang jadi ciphertext.

age adalah tool enkripsi modern yang simpel, dirancang sebagai pengganti PGP untuk kebutuhan sehari-hari. Dia pakai sepasang kunci: public key (untuk mengenkripsi) dan private key (untuk mendekripsi). Di SOPS, kita pakai age sebagai “penyimpan kunci”-nya.

Cara kerjanya bareng-bareng:

  1. SOPS meminta age public key (dari .sops.yaml) untuk mengenkripsi .env → hasilnya .env.enc.
  2. .env.enc di-commit ke git, sedangkan .env masuk .gitignore.
  3. Di device lain, tinggal git pull lalu SOPS pakai age private key lokal untuk mendekripsi .env.enc → .env siap dipakai.

Private key nggak pernah ikut ke git. Aman, dan workflow-nya seamless.


Tutorial Lengkap
#

1. Install SOPS dan age
#

Windows (winget):

winget install FiloSottile.age
winget install Mozilla.sops

macOS (brew):

brew install age sops

Linux (Debian/Ubuntu):

sudo apt install age
# sops: download binary dari GitHub releases

2. Generate age key
#

Di Windows, buat dulu folder penyimpanan key lalu generate:

mkdir "$env:APPDATA\sops\age" -Force
age-keygen -o "$env:APPDATA\sops\age\keys.txt"
Catat public key yang muncul di output (formatnya age1xxxxxxxxxxxxx...). Ini yang nanti dipakai di .sops.yaml. Yang di file keys.txt itu private key — jangan pernah commit atau share.
Catatan path: SOPS di Windows mencari key default di %APPDATA%\sops\age\keys.txt, sedangkan di macOS/Linux di ~/.config/sops/age/keys.txt. Kalau kamu sync project yang sama antara Windows dan Mac/Linux, path key-nya beda tempat di tiap OS — itu wajar, nggak masalah. Key-nya cuma perlu ada secara lokal di masing-masing device.

3. Copy private key ke device lain
#

Kalau device kedua beda OS, salin isi file key ke path yang sesuai di device tersebut:

  • Dari Mac/Linux: ~/.config/sops/age/keys.txt → ke Windows: %APPDATA%\sops\age\keys.txt
  • Dari Windows: %APPDATA%\sops\age\keys.txt → ke Mac/Linux: ~/.config/sops/age/keys.txt

Cara aman memindahkannya? Lewat password manager (Bitwarden, KeePass, dll.) atau media offline. Jangan dikirim lewat chat.

4. Buat file .sops.yaml di root project
#

File ini sama persis di semua OS:

creation_rules:
  - path_regex: \.env(\.enc)?$
    age: age1xxxxxxxxxxxxx...

path_regex memberitahu SOPS file mana yang harus dienkripsi dengan kunci age tersebut — dalam hal ini .env dan .env.enc.

5. Encrypt .env
#

Perintah dasar sebenarnya sops -e .env > .env.enc. TAPI — ini pelajaran berharga dari pengalaman saya — di Windows SOPS suka salah deteksi format file .env, jadi wajib pakai format eksplisit:

sops -e --input-type dotenv --output-type dotenv .env > .env.enc

Cek hasilnya: isi .env.enc sekarang ciphertext, dan ada metadata SOPS di dalamnya (termasuk fingerprint age key-mu).

6. Decrypt .env.enc
#

sops -d --input-type dotenv --output-type dotenv .env.enc > .env

7. Bikin script pembantu biar nggak salah ketik
#

Karena format eksplisit itu panjang dan gampang lupa, saya bikin dua file PowerShell di root project. encrypt.ps1:

sops -e --input-type dotenv --output-type dotenv .env > .env.enc
if ($LASTEXITCODE -eq 0) {
    Write-Host "✅ .env.enc updated"
} else {
    Write-Host "❌ Encrypt gagal, cek error di atas" -ForegroundColor Red
}

decrypt.ps1 (jangan typo kayak saya dulu, decypt wkwk):

sops -d --input-type dotenv --output-type dotenv .env.enc > .env
if ($LASTEXITCODE -eq 0) {
    Write-Host "✅ .env decrypted"
} else {
    Write-Host "❌ Decrypt gagal, cek error di atas" -ForegroundColor Red
}

8. Setup git yang benar
#

# .gitignore
.env

Yang masuk git cuma .env.enc dan .sops.yaml. Jangan pernah commit .env atau keys.txt.

Anti-CRLF: supaya masalah \x0d (lihat Troubleshooting) nggak muncul, tambahkan .gitattributes di root project:

*.env.enc text eol=lf

Ini memaksa git menyimpan .env.enc dengan line ending LF, apapun OS-nya.


Tips & Trik
#

  • Backup private key di password manager. Kalau key hilang, .env.enc-mu nggak bisa didekripsi selamanya. Simpan isi keys.txt di Bitwarden/KeePass — bukan di git, bukan di chat.

  • Bisa untuk banyak device sekaligus. Tinggal tambah semua age public key di .sops.yaml:

    creation_rules:
      - path_regex: \.env(\.enc)?$
        age:
          - age1publickeyDevice1...
          - age1publickeyDevice2...
  • Bukan cuma .env. SOPS juga paham format JSON, YAML, dan INI. Mau encrypt config.yaml atau secrets.json juga bisa — tinggal sesuaikan path_regex.

  • Rotasi key itu gampang. Generate key baru, update .sops.yaml, lalu sops -e ulang semua file — SOPS menulis ulang metadata dengan key baru.

  • Bisa dipakai di CI/CD. Di pipeline, masukkan age key lewat secret store (GitHub Actions secrets, dsb.) dan decrypt sebelum build. Sama sekali nggak ada secret yang bocor ke repo.

  • Kebiasaan pakai .env buat nyimpen rahasia juga saya bahas di learning path home server — prinsipnya sama: rahasia jangan pernah hardcode.

  • Kalau kamu kerja multi-device, pastikan juga SSH key GitHub-mu siap di semua OS dan profile git-mu nggak ketuker — biar workflow-nya benar-benar mulus dari ujung ke ujung.


FAQ
#

Aman nggak sih commit .env.enc ke repo publik? Aman, selama private key age nggak ikut ter-commit. Isi .env.enc itu ciphertext — tanpa private key, nggak ada yang bisa membacanya, termasuk kamu sendiri (kalau key-mu hilang wkwk).

Kalau private key-nya hilang gimana? File .env.enc yang lama jadi tidak bisa dibaca. Solusinya: backup key sejak awal di password manager. Kalau terlanjur hilang, generate key baru, update .sops.yaml, dan encrypt ulang semua .env dari device yang masih punya plaintext-nya.

Kenapa path key-nya beda-beda antar OS? Itu default bawaan SOPS (%APPDATA%\sops\age di Windows vs ~/.config/sops/age di Linux/macOS). Nggak perlu disamakan — cukup taruh key di path yang sesuai di tiap device.

Bisa enkripsi untuk beberapa device sekaligus? Bisa. Tambahkan semua public key age sebagai list di .sops.yaml — semua device yang punya private key yang cocok bisa mendekripsi file yang sama.

Kenapa harus pakai --input-type dotenv? Karena ekstensi .env nggak dikenali SOPS secara default, jadi dia bisa salah tebak format (misalnya nganggap JSON) — makanya muncul error “invalid character”. Dengan format eksplisit, SOPS tahu persis harus memperlakukan file sebagai dotenv.


Troubleshooting
#

Error Penyebab Solusi
parsing time "...\x0d": extra text: "\x0d" Line ending CRLF di Windows — karakter \r (\x0d) nyangkut di metadata timestamp SOPS Tambahkan *.env.enc text eol=lf di .gitattributes, atau konversi file dengan dos2unix
Error unmarshalling input json: invalid character 'P' looking for beginning of value SOPS salah deteksi format — mencoba parse file dotenv sebagai JSON Wajib pakai format eksplisit: --input-type dotenv --output-type dotenv
error loading config: no matching creation rules found Nama file nggak cocok dengan path_regex, atau .sops.yaml nggak ketemu dari direktori tempat kamu jalanin sops Sesuaikan regex (misal \.env(\.local)?$), atau jalankan sops dari root project tempat .sops.yaml berada

Penutup
#

Masalah “lupa update .env di laptop” itu klasik banget di workflow multi-device. Dengan SOPS + age, .env kamu ikut ter-versioning di git bareng kodenya — tapi tetap terkunci rapat. Setelah setup sekali, ritualnya cuma dua: encrypt.ps1 sebelum commit, decrypt.ps1 setelah pull. Selesai.

Pernah ngalamin masalah serupa atau punya cara lain yang lebih keren? Cerita di kolom komentar ya 🚀

Terkait


Load Comments