{"id":15171759,"url":"https://github.com/mic92/sops-nix","last_synced_at":"2025-05-14T04:09:50.229Z","repository":{"id":36966350,"uuid":"277461369","full_name":"Mic92/sops-nix","owner":"Mic92","description":"Atomic secret provisioning for NixOS based on sops","archived":false,"fork":false,"pushed_at":"2025-05-04T03:36:50.000Z","size":1216,"stargazers_count":2003,"open_issues_count":75,"forks_count":174,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-04T04:26:08.241Z","etag":null,"topics":["build-with-buildbot","hacktoberfest","nixos","sops"],"latest_commit_sha":null,"homepage":"","language":"Nix","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mic92.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-07-06T06:32:31.000Z","updated_at":"2025-05-03T21:25:33.000Z","dependencies_parsed_at":"2024-04-07T03:35:36.869Z","dependency_job_id":"9ede492a-d342-4ff0-802b-2f98fbef2ad9","html_url":"https://github.com/Mic92/sops-nix","commit_stats":{"total_commits":628,"total_committers":80,"mean_commits":7.85,"dds":0.6337579617834395,"last_synced_commit":"06535d0e3d0201e6a8080dd32dbfde339b94f01b"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fsops-nix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fsops-nix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fsops-nix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fsops-nix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mic92","download_url":"https://codeload.github.com/Mic92/sops-nix/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254070109,"owners_count":22009559,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-with-buildbot","hacktoberfest","nixos","sops"],"created_at":"2024-09-27T09:03:37.838Z","updated_at":"2025-05-14T04:09:45.175Z","avatar_url":"https://github.com/Mic92.png","language":"Nix","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sops-nix\n\n![sops-nix logo](https://github.com/Mic92/sops-nix/releases/download/assets/logo.gif \"Logo of sops-nix\")\n\nAtomic, declarative, and reproducible secret provisioning for NixOS based on [sops](https://github.com/mozilla/sops).\n\n## How it works\n\nSecrets are decrypted from [`sops` files](https://github.com/mozilla/sops#2usage) during\nactivation time. The secrets are stored as one secret per file and access-controlled by full declarative configuration of their users, permissions, and groups.\nGPG keys or `age` keys can be used for decryption, and compatibility shims are supported to enable the use of SSH RSA or SSH Ed25519 keys.\nSops also supports cloud key management APIs such as AWS\nKMS, GCP KMS, Azure Key Vault and Hashicorp Vault. While not\nofficially supported by sops-nix yet, these can be controlled using\nenvironment variables that can be passed to sops.\n\n## Features\n\n- Compatible with all NixOS deployment frameworks: [NixOps](https://github.com/NixOS/nixops), nixos-rebuild, [krops](https://github.com/krebs/krops/), [morph](https://github.com/DBCDK/morph), [nixus](https://github.com/Infinisil/nixus), etc.\n- Version-control friendly: Since all files are encrypted they can be directly committed to version control without worry. Diffs of the secrets are readable, and [can be shown in cleartext](https://github.com/mozilla/sops#showing-diffs-in-cleartext-in-git).\n- CI friendly: Since sops files can be added to the Nix store without leaking secrets, a machine definition can be built as a whole from a repository, without needing to rely on external secrets or services.\n- Home-manager friendly: Provides a home-manager module\n- Works well in teams: sops-nix comes with `nix-shell` hooks that allows multiple people to quickly import all GPG keys.\n  The cryptography used in sops is designed to be scalable: Secrets are only encrypted once with a master key\n  instead of encrypted per machine/developer key.\n- Atomic upgrades: New secrets are written to a new directory which replaces the old directory atomically.\n- Rollback support: If sops files are added to the Nix store, old secrets can be rolled back. This is optional.\n- Fast time-to-deploy: Unlike solutions implemented by NixOps, krops and morph, no extra steps are required to upload secrets.\n- A variety of storage formats: Secrets can be stored in YAML, dotenv, INI, JSON or binary.\n- Minimizes configuration errors: sops files are checked against the configuration at evaluation time.\n\n## Demo\n\nThere is a `configuration.nix` example in the [deployment step](#deploy-example) of our usage example.\n\n## Supported encryption methods\n\nsops-nix supports two basic ways of encryption, GPG and `age`.\n\nGPG is based on [GnuPG](https://gnupg.org/) and encrypts against GPG public keys. Private GPG keys may\nbe used to decrypt the secrets on the target machine. The tool [`ssh-to-pgp`](https://github.com/Mic92/ssh-to-pgp) can\nbe used to derive a GPG key from a SSH (host) key in RSA format.\n\nThe other method is `age` which is based on [`age`](https://github.com/FiloSottile/age).\nThe tool ([`ssh-to-age`](https://github.com/Mic92/ssh-to-age)) can convert SSH host or user keys in Ed25519\nformat to `age` keys.\n\n## Usage example\n\nIf you prefer video over the textual description below, you can also checkout this [6min tutorial](https://www.youtube.com/watch?v=G5f6GC7SnhU) by [@vimjoyer](https://github.com/vimjoyer).\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e1. Install sops-nix\u003c/b\u003e\u003c/summary\u003e\n\nChoose one of the following methods. When using it non-globally with home-manager, refer to [Use with home-manager](#use-with-home-manager).\n\n#### Flakes (current recommendation)\n\nIf you use experimental nix flakes support:\n\n``` nix\n{\n  inputs.sops-nix.url = \"github:Mic92/sops-nix\";\n  # optional, not necessary for the module\n  #inputs.sops-nix.inputs.nixpkgs.follows = \"nixpkgs\";\n\n  outputs = { self, nixpkgs, sops-nix }: {\n    # change `yourhostname` to your actual hostname\n    nixosConfigurations.yourhostname = nixpkgs.lib.nixosSystem {\n      # customize to your system\n      system = \"x86_64-linux\";\n      modules = [\n        ./configuration.nix\n        sops-nix.nixosModules.sops\n      ];\n    };\n  };\n}\n```\n\n#### [`niv`](https://github.com/nmattia/niv) (recommended if not using flakes)\n  First add it to niv:\n  \n```console\n$ niv add Mic92/sops-nix\n```\n\n  Then add the following to your `configuration.nix` in the `imports` list:\n  \n```nix\n{\n  imports = [ \"${(import ./nix/sources.nix).sops-nix}/modules/sops\" ];\n}\n```\n  \n#### `fetchTarball`\n\n  Add the following to your `configuration.nix`:\n\n```nix\n{\n  imports = let\n    # replace this with an actual commit id or tag\n    commit = \"298b235f664f925b433614dc33380f0662adfc3f\";\n  in [ \n    \"${builtins.fetchTarball {\n      url = \"https://github.com/Mic92/sops-nix/archive/${commit}.tar.gz\";\n      # replace this with an actual hash\n      sha256 = \"0000000000000000000000000000000000000000000000000000\";\n    }}/modules/sops\"\n  ];\n}\n```\n  \n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e2. Generate a key for yourself\u003c/b\u003e\u003c/summary\u003e\n\nThis key will be used for you to edit secrets.\n\nYou can generate yourself a key:\n\n```console\n# for age..\n$ mkdir -p ~/.config/sops/age\n$ age-keygen -o ~/.config/sops/age/keys.txt\n# or to convert an ssh ed25519 key to an age key\n$ mkdir -p ~/.config/sops/age\n$ nix-shell -p ssh-to-age --run \"ssh-to-age -private-key -i ~/.ssh/id_ed25519 \u003e ~/.config/sops/age/keys.txt\"\n# for GPG \u003e= version 2.1.17\n$ gpg --full-generate-key\n# for GPG \u003c 2.1.17\n$ gpg --default-new-key-algo rsa4096 --gen-key\n```\n\nOr you can use the `ssh-to-pgp` tool to get a GPG key from an SSH key: \n```console\n$ nix-shell -p gnupg -p ssh-to-pgp --run \"ssh-to-pgp -private-key -i $HOME/.ssh/id_rsa | gpg --import --quiet\"\n2504791468b153b8a3963cc97ba53d1919c5dfd4\n# This exports the public key\n$ nix-shell -p ssh-to-pgp --run \"ssh-to-pgp -i $HOME/.ssh/id_rsa -o $USER.asc\"\n2504791468b153b8a3963cc97ba53d1919c5dfd4\n```\n(Note that `ssh-to-pgp` only supports RSA keys; to use Ed25519 keys, use `age`.)  \nIf you get the following,\n```console\nssh-to-pgp: failed to parse private ssh key: ssh: this private key is passphrase protected\n```\nthen your SSH key is encrypted with your password and you will need to create an unencrypted copy temporarily.\n```console\n$ cp $HOME/.ssh/id_rsa /tmp/id_rsa\n$ ssh-keygen -p -N \"\" -f /tmp/id_rsa\n$ nix-shell -p gnupg -p ssh-to-pgp --run \"ssh-to-pgp -private-key -i /tmp/id_rsa | gpg --import --quiet\"\n$ rm /tmp/id_rsa\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e How to find the public key of an `age` key \u003c/summary\u003e\n\nIf you generated an `age` key, the `age` public key can be found via `age-keygen -y $PATH_TO_KEY`:\n```console\n$ age-keygen -y ~/.config/sops/age/keys.txt\nage12zlz6lvcdk6eqaewfylg35w0syh58sm7gh53q5vvn7hd7c6nngyseftjxl\n```\n\nOtherwise, you can convert an existing SSH key into an `age` public key:\n```console\n$ nix-shell -p ssh-to-age --run \"ssh-to-age \u003c ~/.ssh/id_ed25519.pub\"\n# or\n$ nix-shell -p ssh-to-age --run \"ssh-add -L | ssh-to-age\"\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e How to find the GPG fingerprint of a key \u003c/summary\u003e\n\nInvoke this command and look for your key:\n```console\n$ gpg --list-secret-keys\n/tmp/tmp.JA07D1aVRD/pubring.kbx\n-------------------------------\nsec   rsa2048 1970-01-01 [SCE]\n      9F89C5F69A10281A835014B09C3DC61F752087EF\nuid           [ unknown] root \u003croot@localhost\u003e\n```\n\nThe fingerprint here is `9F89C5F69A10281A835014B09C3DC61F752087EF`.\n\u003c/details\u003e\n\nYour `age` public key or GPG fingerprint can be written to your [`.sops.yaml`](https://github.com/getsops/sops#using-sops-yaml-conf-to-select-kms-pgp-and-age-for-new-files) in the root of your configuration directory or repository:\n```yaml\n# This example uses YAML anchors which allows reuse of multiple keys \n# without having to repeat yourself.\n# Also see https://github.com/Mic92/dotfiles/blob/d6114726d859df36ccaa32891c4963ae5717ef7f/nixos/.sops.yaml\n# for a more complex example.\nkeys:\n  - \u0026admin_alice 2504791468b153b8a3963cc97ba53d1919c5dfd4\n  - \u0026admin_bob age12zlz6lvcdk6eqaewfylg35w0syh58sm7gh53q5vvn7hd7c6nngyseftjxl\ncreation_rules:\n  - path_regex: secrets/[^/]+\\.(yaml|json|env|ini)$\n    key_groups:\n    - pgp:\n      - *admin_alice\n      age:\n      - *admin_bob\n```\n\n**Note:**\nBe sure to not include a `-` before subsequent key types under `key_groups`\n(i.e. `age` in the above example should not have a `-` in front).\nThis will otherwise cause sops to require multiple keys (shamir secret sharing)\nto decrypt a secret, which breaks normal sops-nix usage.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e3. Get a public key for your target machine\u003c/b\u003e\u003c/summary\u003e\n\nThe easiest way to add new machines is by using SSH host keys (this requires OpenSSH to be enabled).  \n\nIf you are using `age`, the `ssh-to-age` tool can be used to convert any SSH Ed25519 public key to the `age` format:\n```console\n$ nix-shell -p ssh-to-age --run 'ssh-keyscan example.com | ssh-to-age'\nage1rgffpespcyjn0d8jglk7km9kfrfhdyev6camd3rck6pn8y47ze4sug23v3\n$ nix-shell -p ssh-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age'\nage1rgffpespcyjn0d8jglk7km9kfrfhdyev6camd3rck6pn8y47ze4sug23v3\n```\n\nFor GPG, since sops does not natively support SSH keys yet, sops-nix supports a conversion tool (`ssh-to-pgp`) to store them as GPG keys:\n\n```console\n$ ssh root@server01 \"cat /etc/ssh/ssh_host_rsa_key\" | nix-shell -p ssh-to-pgp --run \"ssh-to-pgp -o server01.asc\"\n# or with sudo\n$ ssh youruser@server01 \"sudo cat /etc/ssh/ssh_host_rsa_key\" | nix-shell -p ssh-to-pgp --run \"ssh-to-pgp -o server01.asc\"\n0fd60c8c3b664aceb1796ce02b318df330331003\n# or just read them locally/over ssh\n$ nix-shell -p ssh-to-pgp --run \"ssh-to-pgp -i /etc/ssh/ssh_host_rsa_key -o server01.asc\"\n0fd60c8c3b664aceb1796ce02b318df330331003\n```\n\nThe output of these commands is the identifier for the server's key, which can be added to your `.sops.yaml`:\n\n```yaml\nkeys:\n  - \u0026admin_alice 2504791468b153b8a3963cc97ba53d1919c5dfd4\n  - \u0026admin_bob age12zlz6lvcdk6eqaewfylg35w0syh58sm7gh53q5vvn7hd7c6nngyseftjxl\n  - \u0026server_azmidi 0fd60c8c3b664aceb1796ce02b318df330331003\n  - \u0026server_nosaxa age1rgffpespcyjn0d8jglk7km9kfrfhdyev6camd3rck6pn8y47ze4sug23v3\ncreation_rules:\n  - path_regex: secrets/[^/]+\\.(yaml|json|env|ini)$\n    key_groups:\n    - pgp:\n      - *admin_alice\n      - *server_azmidi\n      age:\n      - *admin_bob\n      - *server_nosaxa\n  - path_regex: secrets/azmidi/[^/]+\\.(yaml|json|env|ini)$\n    key_groups:\n    - pgp:\n      - *admin_alice\n      - *server_azmidi\n      age:\n      - *admin_bob\n```\n\nIf you prefer having a separate GPG key, see [Use with GPG instead of SSH keys](#use-with-GPG-instead-of-SSH-keys).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e4. Create a sops file\u003c/b\u003e\u003c/summary\u003e\n\nTo create a sops file you need write a `.sops.yaml` as described above.\n\nWhen using GnuPG you also need to import your personal GPG key\n(and your colleagues) and your servers into your GPG key chain.\n\n\u003cdetails\u003e\n\u003csummary\u003esops-nix can automate the import of GPG keys with a hook for nix-shell, allowing public\nkeys to be shared via version control (i.e. git).\u003c/summary\u003e\n\n```nix\n# shell.nix\nwith import \u003cnixpkgs\u003e {};\nlet\n  sops-nix = builtins.fetchTarball {\n    url = \"https://github.com/Mic92/sops-nix/archive/master.tar.gz\";\n  };\nin\nmkShell {\n  # imports all files ending in .asc/.gpg\n  sopsPGPKeyDirs = [ \n    \"${toString ./.}/keys/hosts\"\n    \"${toString ./.}/keys/users\"\n  ];\n  # Also single files can be imported.\n  #sopsPGPKeys = [ \n  #  \"${toString ./.}/keys/users/mic92.asc\"\n  #  \"${toString ./.}/keys/hosts/server01.asc\"\n  #];\n  \n  # This hook can also import gpg keys into its own seperate\n  # gpg keyring instead of using the default one. This allows\n  # to isolate otherwise unrelated server keys from the user gpg keychain.\n  # By uncommenting the following lines, it will set GNUPGHOME\n  # to .git/gnupg. \n  # Storing it inside .git prevents accedentially commiting private keys.\n  # After setting this option you will also need to import your own\n  # private key into keyring, i.e. using a a command like this \n  # (replacing 0000000000000000000000000000000000000000 with your fingerprint)\n  # $ (unset GNUPGHOME; gpg --armor --export-secret-key 0000000000000000000000000000000000000000) | gpg --import\n  #sopsCreateGPGHome = true;\n  # To use a different directory for gpg dirs set sopsGPGHome\n  #sopsGPGHome = \"${toString ./.}/../gnupg\";\n  \n  nativeBuildInputs = [\n    (pkgs.callPackage sops-nix {}).sops-import-keys-hook\n  ];\n}\n```\n\nA valid directory structure for this might look like:\n\n```console\n$ tree .\n.\n├── keys\n│   ├── hosts\n│   │   └── server01.asc\n│   └── users\n│       └── mic92.asc\n```\n\n\u003c/details\u003e\n\nAfter configuring `.sops.yaml`, you can open a new file with sops:\n\n```console\n$ nix-shell -p sops --run \"sops secrets/example.yaml\"\n```\n\nThis will start your configured editor located at the `$EDITOR` environment variable.  \nAn example secret file might be:\n```yaml\n# Files must always have a string value\nexample-key: example-value\n# Nesting the key results in the creation of directories.\n# These directories will be owned by root:keys and have permissions 0751.\nmyservice:\n  my_subdir:\n    my_secret: password1\n```\n\nAn example result when saving this file could be:\n\n```\nexample-key: ENC[AES256_GCM,data:AB8XMyid4P7mXdjj+A==,iv:RRsZC+V+3w22pOi/2TCjBYn/0OYsNGCu5CT1ZBSKGi0=,tag:zT5mlujrSuA6KKxLKL8CMQ==,type:str]\n#ENC[AES256_GCM,data:59QWbzCQCP7kLdhyjFOZe503MgegN0kv505PBNHwjp6aYztDHwx2N9+A1Bz6G/vWYo+4LpBo8/s=,iv:89q3ZXgM1wBUg5G29ROor3VXrO3QFGCvfwDoA3+G14M=,tag:hOSnEZ6DKycnF37LCXOjzg==,type:comment]\n#ENC[AES256_GCM,data:kUuJCkDE9JT9C+kdNe0CSB3c+gmgE4We1OoX4C1dWeoZCw/o9/09CzjRi9eOBUEL0P1lrt+g6V2uXFVq4n+M8UPGUAbRUr3A,iv:nXJS8wqi+ephoLynm9Nxbqan0V5dBstctqP0WxniSOw=,tag:ALx396Z/IPCwnlqH//Hj3g==,type:comment]\nmyservice:\n    my_subdir:\n        my_secret: ENC[AES256_GCM,data:hcRk5ERw60G5,iv:3Ur6iH1Yu0eu2otcEv+hGRF5kTaH6HSlrofJ5JXvewA=,tag:hpECXFnMhGNnAxxzuGW5jg==,type:str]\nsops:\n    kms: []\n    gcp_kms: []\n    azure_kv: []\n    hc_vault: []\n    age:\n        - recipient: age12zlz6lvcdk6eqaewfylg35w0syh58sm7gh53q5vvn7hd7c6nngyseftjxl\n          enc: |\n            -----BEGIN AGE ENCRYPTED FILE-----\n            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1dFYvSTRHa3IwTVpuZjEz\n            SDZZQnc5a0dGVGEzNXZmNEY5NlZDbVgyNVU0Clo3ZC9MRGp4SHhLUTVCeWlOUUxS\n            MEtPdW4rUHhjdFB6bFhyUXRQTkRpWjAKLS0tIDVTbWU2V3dJNUZrK1A5U0c5bkc0\n            S3VINUJYc3VKcjBZbHVqcGJBSlVPZWcKqPXE01ienWDbTwxo+z4dNAizR3t6uTS+\n            KbmSOK1v61Ri0bsM5HItiMP+fE3VCyhqMBmPdcrR92+3oBmiSFnXPA==\n            -----END AGE ENCRYPTED FILE-----\n        - recipient: age18jtffqax5v0t6ehh4ypaefl4mfhcrhn6ek3p80mhfp9psx6pd35qew2ww3\n          enc: |\n            -----BEGIN AGE ENCRYPTED FILE-----\n            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzT3FxcDEzaFRQOVFpNkg2\n            Skw4WEIxZzNTWkNBaDRhcUN2ejY4QTAwTERvCkx2clIzT2wyaFJZcjl0RkFXL2p6\n            enhqVEZ3ZkNKUU5jTlUxRC9Lb090TzAKLS0tIDBEaG00RFJDZ3ZVVjBGUWJkRHdQ\n            YkpudG43eURPVWJUejd3Znk5Z29lWlkK0cIngn2qdmiOE5rHOHxTRcjfZYuY3Ej7\n            Yy7nYxMwTdYsm/V6Lp2xm8hvSzBEIFL+JXnSTSwSHnCIfgle5BRbug==\n            -----END AGE ENCRYPTED FILE-----\n    lastmodified: \"2021-11-20T16:21:10Z\"\n    mac: ENC[AES256_GCM,data:5ieT/yv1GZfZFr+OAZ/DBF+6DJHijRXpjNI2kfBun3KxDkyjiu/OFmAbsoVFY/y6YCT3ofl4Vwa56Veo3iYj4njgxyLpLuD1B6zkMaNXaPywbAhuMho7bDGEJZHrlYOUNLdBqW2ytTuFA095IncXE8CFGr38A2hfjcputdHk4R4=,iv:UcBXWtaquflQFNDphZUqahADkeege5OjUY38pLIcFkU=,tag:yy+HSMm+xtX+vHO78nej5w==,type:str]\n    pgp: []\n    unencrypted_suffix: _unencrypted\n    version: 3.7.1\n```\n\nIf you add a new host to your `.sops.yaml` file, you will need to update the keys for all secrets that are used by the new host.  This can be done like so:\n```\n$ nix-shell -p sops --run \"sops updatekeys secrets/example.yaml\"\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary id=\"deploy-example\"\u003e\u003cb\u003e5. Deploy\u003c/b\u003e\u003c/summary\u003e\n\nIf you derived your server public key from SSH, all you need in your `configuration.nix` is:\n\n```nix\n{\n  imports = [ \u003csops-nix/modules/sops\u003e ];\n  # This will add secrets.yml to the nix store\n  # You can avoid this by adding a string to the full path instead, i.e.\n  # sops.defaultSopsFile = \"/root/.sops/secrets/example.yaml\";\n  sops.defaultSopsFile = ./secrets/example.yaml;\n  # This will automatically import SSH keys as age keys\n  sops.age.sshKeyPaths = [ \"/etc/ssh/ssh_host_ed25519_key\" ];\n  # This is using an age key that is expected to already be in the filesystem\n  sops.age.keyFile = \"/var/lib/sops-nix/key.txt\";\n  # This will generate a new key if the key specified above does not exist\n  sops.age.generateKey = true;\n  # This is the actual specification of the secrets.\n  sops.secrets.example-key = {};\n  sops.secrets.\"myservice/my_subdir/my_secret\" = {};\n}\n```\n\nOn `nixos-rebuild switch` this will make the keys accessible \nvia `/run/secrets/example-key` and `/run/secrets/myservice/my_subdir/my_secret`:\n\n```console\n$ cat /run/secrets/example-key\nexample-value\n$ cat /run/secrets/myservice/my_subdir/my_secret\npassword1\n```\n\n`/run/secrets` is a symlink to `/run/secrets.d/{number}`:\n\n```console\n$ ls -la /run/secrets\nlrwxrwxrwx 16 root 12 Jul  6:23  /run/secrets -\u003e /run/secrets.d/1\n```\n\n\u003c/details\u003e\n\n## Set secret permission/owner and allow services to access it\n\nBy default secrets are owned by `root:root`. Furthermore\nthe parent directory `/run/secrets.d` is only owned by\n`root` and the `keys` group has read access to it:\n\n``` console\n$ ls -la /run/secrets.d/1\ntotal 24\ndrwxr-x--- 2 root keys   0 Jul 12  6:23 .\ndrwxr-x--- 3 root keys   0 Jul 12  6:23 ..\n-r-------- 1 root root  20 Jul 12  6:23 example-secret\n```\n\nThe secrets option has further parameter to change secret permission.\nConsider the following nixos configuration example:\n\n```nix\n{\n  # Permission modes are in octal representation (same as chmod),\n  # the digits represent: user|group|others\n  # 7 - full (rwx)\n  # 6 - read and write (rw-)\n  # 5 - read and execute (r-x)\n  # 4 - read only (r--)\n  # 3 - write and execute (-wx)\n  # 2 - write only (-w-)\n  # 1 - execute only (--x)\n  # 0 - none (---)\n  sops.secrets.example-secret.mode = \"0440\";\n  # Either a user id or group name representation of the secret owner\n  # It is recommended to get the user name from `config.users.users.\u003c?name\u003e.name` to avoid misconfiguration\n  sops.secrets.example-secret.owner = config.users.users.nobody.name;\n  # Either the group id or group name representation of the secret group\n  # It is recommended to get the group name from `config.users.users.\u003c?name\u003e.group` to avoid misconfiguration\n  sops.secrets.example-secret.group = config.users.users.nobody.group;\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eThis example configures secrets for buildkite, a CI agent;\nthe service needs a token and a SSH private key to function.\u003c/summary\u003e\n\n```nix\n{ pkgs, config, ... }:\n{\n  services.buildkite-agents.builder = {\n    enable = true;\n    tokenPath = config.sops.secrets.buildkite-token.path;\n    privateSshKeyPath = config.sops.secrets.buildkite-ssh-key.path;\n\n    runtimePackages = [\n      pkgs.gnutar\n      pkgs.bash\n      pkgs.nix\n      pkgs.gzip\n      pkgs.git\n    ];\n\n  };\n\n  sops.secrets.buildkite-token.owner = config.users.buildkite-agent-builder.name;\n  sops.secrets.buildkite-ssh-key.owner = config.users.buildkite-agent-builder.name;\n}\n```\n\n\u003c/details\u003e\n\n## Restarting/reloading systemd units on secret change\n\nIt is possible to restart or reload units when a secret changes or is newly initialized.\n\nThis behavior can be configured per-secret:\n```nix\n{\n  sops.secrets.\"home-assistant-secrets.yaml\" = {\n    restartUnits = [ \"home-assistant.service\" ];\n    # there is also `reloadUnits` which acts like a `reloadTrigger` in a NixOS systemd service\n  };\n}\n```\n\n## Symlinks to other directories\n\nSome services might expect files in certain locations.\nUsing the `path` option a symlink to this directory can\nbe created:\n\n```nix\n{\n  sops.secrets.\"home-assistant-secrets.yaml\" = {\n    owner = \"hass\";\n    path = \"/var/lib/hass/secrets.yaml\";\n  };\n}\n```\n\n```console\n$ ls -la /var/lib/hass/secrets.yaml\nlrwxrwxrwx 1 root root 40 Jul 19 22:36 /var/lib/hass/secrets.yaml -\u003e /run/secrets/home-assistant-secrets.yaml\n```\n\n## Setting a user's password\n\nsops-nix has to run after NixOS creates users (in order to specify what users own a secret.)\nThis means that it's not possible to set `users.users.\u003cname\u003e.hashedPasswordFile` to any secrets managed by sops-nix.\nTo work around this issue, it's possible to set `neededForUsers = true` in a secret.\nThis will cause the secret to be decrypted to `/run/secrets-for-users` instead of `/run/secrets` before NixOS creates users.\nAs users are not created yet, it's not possible to set an owner for these secrets.\n\nThe password must be stored as a hash for this to work, which can be created with the command `mkpasswd`\n```console\n$ echo \"password\" | mkpasswd -s\n$y$j9T$WFoiErKnEnMcGq0ruQK4K.$4nJAY3LBeBsZBTYSkdTOejKU6KlDmhnfUV3Ll1K/1b.\n```\n\n```nix\n{ config, ... }: {\n  sops.secrets.my-password.neededForUsers = true;\n\n  users.users.mic92 = {\n    isNormalUser = true;\n    hashedPasswordFile = config.sops.secrets.my-password.path;\n  };\n}\n```\n\n**Note:** If you are using Impermanence, the key used for secret decryption (`sops.age.keyFile`, or the host SSH keys) must be in a persisted directory,\nloaded early enough during boot. For example:\n\n```nix\nsops.age.keyFile = \"/nix/persist/var/lib/sops-nix/key.txt\";\n```\n\nor:\n\n```nix\nfileSystems.\"/etc/ssh\".neededForBoot = true;\n```\n\n## Different file formats\n\nAt the moment we support the following file formats: YAML, JSON, INI, dotenv and binary.\n\nsops-nix allows specifying multiple sops files in different file formats:\n\n```nix\n{\n  imports = [ \u003csops-nix/modules/sops\u003e ];\n  # The default sops file used for all secrets can be controlled using `sops.defaultSopsFile`\n  sops.defaultSopsFile = ./secrets.yaml;\n  # If you use something different from YAML, you can also specify it here:\n  #sops.defaultSopsFormat = \"yaml\";\n  sops.secrets.github_token = {\n    # The sops file can be also overwritten per secret...\n    sopsFile = ./other-secrets.json;\n    # ... as well as the format\n    format = \"json\";\n  };\n}\n```\n\n### YAML\n\nOpen a new file with sops ending in `.yaml`:\n\n```console\n$ sops secrets.yaml\n```\n\nThen, put in the following content:\n\n```yaml\ngithub_token: 4a6c73f74928a9c4c4bc47379256b72e598e2bd3\nssh_key: |\n  -----BEGIN OPENSSH PRIVATE KEY-----\n  b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n  QyNTUxOQAAACDENhLwQI4v/Ecv65iCMZ7aZAL+Sdc0Cqyjkd012XwJzQAAAJht4at6beGr\n  egAAAAtzc2gtZWQyNTUxOQAAACDENhLwQI4v/Ecv65iCMZ7aZAL+Sdc0Cqyjkd012XwJzQ\n  AAAEBizgX7v+VMZeiCtWRjpl95dxqBWUkbrPsUSYF3DGV0rsQ2EvBAji/8Ry/rmIIxntpk\n  Av5J1zQKrKOR3TXZfAnNAAAAE2pvZXJnQHR1cmluZ21hY2hpbmUBAg==\n  -----END OPENSSH PRIVATE KEY-----\n```\n\nYou can include it like this in your `configuration.nix`:\n\n```nix\n{\n  sops.defaultSopsFile = ./secrets.yaml;\n  # YAML is the default \n  #sops.defaultSopsFormat = \"yaml\";\n  sops.secrets.github_token = {\n    format = \"yaml\";\n    # can be also set per secret\n    sopsFile = ./secrets.yaml;\n  };\n}\n```\n\n### JSON\n\nOpen a new file with sops ending in `.json`:\n\n```console\n$ sops secrets.json\n```\n\nThen, put in the following content:\n\n``` json\n{\n  \"github_token\": \"4a6c73f74928a9c4c4bc47379256b72e598e2bd3\",\n  \"ssh_key\": \"-----BEGIN OPENSSH PRIVATE KEY-----\\\\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\\\\nQyNTUxOQAAACDENhLwQI4v/Ecv65iCMZ7aZAL+Sdc0Cqyjkd012XwJzQAAAJht4at6beGr\\\\negAAAAtzc2gtZWQyNTUxOQAAACDENhLwQI4v/Ecv65iCMZ7aZAL+Sdc0Cqyjkd012XwJzQ\\\\nAAAEBizgX7v+VMZeiCtWRjpl95dxqBWUkbrPsUSYF3DGV0rsQ2EvBAji/8Ry/rmIIxntpk\\\\nAv5J1zQKrKOR3TXZfAnNAAAAE2pvZXJnQHR1cmluZ21hY2hpbmUBAg==\\\\n-----END OPENSSH PRIVATE KEY-----\\\\n\"\n}\n```\n\nYou can include it like this in your `configuration.nix`:\n\n```nix\n{\n  sops.defaultSopsFile = ./secrets.json;\n  # YAML is the default \n  sops.defaultSopsFormat = \"json\";\n  sops.secrets.github_token = {\n    format = \"json\";\n    # can be also set per secret\n    sopsFile = ./secrets.json;\n  };\n}\n```\n\n### Binary\n\nThis format allows to encrypt an arbitrary binary format that can't be put into\nJSON/YAML files. Unlike the other two formats, for binary files, one file corresponds to one secret.\n\nTo encrypt an binary file use the following command:\n\n``` console\n$ sops -e /etc/krb5/krb5.keytab \u003e krb5.keytab\n# an example of what this might result in:\n$ head krb5.keytab\n{\n        \"data\": \"ENC[AES256_GCM,data:bIsPHrjrl9wxvKMcQzaAbS3RXCI2h8spw2Ee+KYUTsuousUBU6OMIdyY0wqrX3eh/1BUtl8H9EZciCTW29JfEJKfi3ackGufBH+0wp6vLg7r,iv:TlKiOmQUeH3+NEdDUMImg1XuXg/Tv9L6TmPQrraPlCQ=,tag:dVeVvRM567NszsXKK9pZvg==,type:str]\",\n        \"sops\": {\n                \"kms\": null,\n                \"gcp_kms\": null,\n                \"azure_kv\": null,\n                \"lastmodified\": \"2020-07-06T06:21:06Z\",\n                \"mac\": \"ENC[AES256_GCM,data:ISjUzaw/5mNiwypmUrOk2DAZnlkbnhURHmTTYA3705NmRsSyUh1PyQvCuwglmaHscwl4GrsnIz4rglvwx1zYa+UUwanR0+VeBqntHwzSNiWhh7qMAQwdUXmdCNiOyeGy6jcSDsXUeQmyIWH6yibr7hhzoQFkZEB7Wbvcw6Sossk=,iv:UilxNvfHN6WkEvfY8ZIJCWijSSpLk7fqSCWh6n8+7lk=,tag:HUTgyL01qfVTCNWCTBfqXw==,type:str]\",\n                \"pgp\": [\n                        {\n\n```\n\nIt can be decrypted again like this:\n\n``` console\n$ sops -d krb5.keytab \u003e /tmp/krb5.keytab\n```\n\nThis is how it can be included in your `configuration.nix`:\n\n```nix\n{\n  sops.secrets.krb5-keytab = {\n    format = \"binary\";\n    sopsFile = ./krb5.keytab;\n  };\n}\n```\n\n## Emit plain file for yaml and json formats\n\nBy default, sops-nix extracts a single key from yaml and json files. If you\nneed the plain file instead of extracting a specific key from the input document,\nyou can set `key` to an empty string.\n\nFor example, the input document `my-config.yaml` likes this:\n\n```yaml\nmy-secret1: ENC[AES256_GCM,data:tkyQPQODC3g=,iv:yHliT2FJ74EtnLIeeQtGbOoqVZnF0q5HiXYMJxYx6HE=,tag:EW5LV4kG4lcENaN2HIFiow==,type:str]\nmy-secret2: ENC[AES256_GCM,data:tkyQPQODC3g=,iv:yHliT2FJ74EtnLIeeQtGbOoqVZnF0q5HiXYMJxYx6HE=,tag:EW5LV4kG4lcENaN2HIFiow==,type:str]\nsops:\n    kms: []\n    gcp_kms: []\n    azure_kv: []\n    hc_vault: []\n...\n```\n\nThis is how it can be included in your NixOS module:\n\n```nix\n{\n  sops.secrets.my-config = {\n    format = \"yaml\";\n    sopsFile = ./my-config.yaml;\n    key = \"\";\n  };\n}\n```\n\nThen, it will be mounted as `/run/secrets/my-config`:\n\n```yaml\nmy-secret1: hello\nmy-secret2: hello\n```\n\n## Use with home manager\n\nsops-nix also provides a home-manager module.\nThis module provides a subset of features provided by the system-wide sops-nix since features like the creation of the ramfs and changing the owner of the secrets are not available for non-root users.\n\nThe home-manager module requires systemd/user as it runs a service called `sops-nix.service` rather than an activation script.\nWhile the sops-nix _system_ module decrypts secrets to the system non-persistent `/run/secrets`, the _home-manager_ module places them in the users non-persistent `$XDG_RUNTIME_DIR/secrets.d`.\nAdditionally secrets are symlinked to the users home at `$HOME/.config/sops-nix/secrets` which are referenced for the `.path` value in sops-nix.\nThis requires that the home-manager option `home.homeDirectory` is set to determine the home-directory on evaluation.  It will have to be manually set if home-manager is configured as stand-alone or on non NixOS systems.\n\nDepending on whether you use home-manager system-wide or stand-alone using a home.nix, you have to import it in a different way.\nThis example shows the `flake` approach from the recommended example [Install: Flakes (current recommendation)](#Flakes (current recommendation))\n\n```nix\n{\n  # NixOS system-wide home-manager configuration\n  home-manager.sharedModules = [\n    inputs.sops-nix.homeManagerModules.sops\n  ];\n}\n```\n\n```nix\n{\n  # Configuration via home.nix\n  imports = [\n    inputs.sops-nix.homeManagerModules.sops\n  ];\n}\n```\n\nThis example show the `channel` approach from the example [Install: nix-channel](#nix-channel). All other methods work as well. \n\n```nix\n{\n  # NixOS system-wide home-manager configuration\n  home-manager.sharedModules = [\n    \u003csops-nix/modules/home-manager/sops.nix\u003e\n  ];\n}\n```\n\n```nix\n{\n  # Configuration via home.nix\n  imports = [\n    \u003csops-nix/modules/home-manager/sops.nix\u003e\n  ];\n}\n```\n\nThe actual sops configuration is in the `sops` namespace in your home.nix (or in the `home-manager.users.\u003cname\u003e` namespace when using home-manager system-wide):\n```nix\n{\n  sops = {\n    age.keyFile = \"/home/user/.age-key.txt\"; # must have no password!\n    # It's also possible to use a ssh key, but only when it has no password:\n    #age.sshKeyPaths = [ \"/home/user/path-to-ssh-key\" ];\n    defaultSopsFile = ./secrets.yaml;\n    secrets.test = {\n      # sopsFile = ./secrets.yml.enc; # optionally define per-secret files\n\n      # %r gets replaced with a runtime directory, use %% to specify a '%'\n      # sign. Runtime dir is $XDG_RUNTIME_DIR on linux and $(getconf\n      # DARWIN_USER_TEMP_DIR) on darwin.\n      path = \"%r/test.txt\"; \n    };\n  };\n}\n```\n\nThe secrets are decrypted in a systemd user service called `sops-nix`, so other services needing secrets must order after it:\n```nix\n{\n  systemd.user.services.mbsync.unitConfig.After = [ \"sops-nix.service\" ];\n}\n```\n\n### Qubes Split GPG support\n\nIf you are using Qubes with the [Split GPG](https://www.qubes-os.org/doc/split-gpg),\nthen you can configure sops to utilize the `qubes-gpg-client-wrapper` with the `sops.gnupg.qubes-split-gpg` options.\nThe example above updated looks like this:\n```nix\n{\n  sops = {\n    gnupg.qubes-split-gpg = {\n      enable = true;\n      domain = \"vault-gpg\";\n    };\n    defaultSopsFile = ./secrets.yaml;\n    secrets.test = {\n      # sopsFile = ./secrets.yml.enc; # optionally define per-secret files\n\n      # %r gets replaced with a runtime directory, use %% to specify a '%'\n      # sign. Runtime dir is $XDG_RUNTIME_DIR on linux and $(getconf\n      # DARWIN_USER_TEMP_DIR) on darwin.\n      path = \"%r/test.txt\";\n    };\n  };\n}\n```\n\n## Use with GPG instead of SSH keys\n\nIf you prefer having a separate GPG key, sops-nix also comes with a helper tool, `sops-init-gpg-key`:\n\n```console\n$ nix run github:Mic92/sops-nix#sops-init-gpg-key -- --hostname server01 --gpghome /tmp/newkey\n# You can use the following command to save it to a file:\n$ cat \u003e server01.asc \u003c\u003cEOF\n-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQENBF8L/iQBCACroEaUfvPBMMorNepNQmideOtNztALejgEJ5wZmxabck+qC1Gb\nNWe3tmvChXVHgL7DzodSUfX1PuIjTTeRr2clMXtISPFIsBlRQb4MiErZfsardITM\nn4WScg8sTb4nnqEOJiRknwAhBryIjH8kkCXxKlYK67re281dIK4dKBMIolFADlyv\nwyHurJ7NPpHxR2WXHcIqXX1DaT6RvGQvZHMpfctob8k/QD4CyV6QwG5IVACQ/tuC\nbEUggrkGw+g+XdeieUfWbRsHM4C4pv8BNwA/EYD5d0eKI+rshSPoTT+hcGn8Uh8w\nMVQ8PVs6jWMMOAF1JH/stoPr9Yha+TGbMRi5ABEBAAG0GHNlcnZlcjAxIDxyb290\nQHNlcnZlcjAxPokBTgQTAQgAOBYhBOTKhnaPF2rrbAFVQVOvjX8UlhOxBQJfC/4k\nAhsvBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEFOvjX8UlhOx1XIH/jUOrSR2\nwuoqFiHcqaDPgXmTVJk8QanVkmiP3tk0mz5rRKrDX2eX5GnHqYR4PfpjUYNzedQE\nsGyTjl7+DvglWJ2Q8m3yD/9+1agBmeqEVQlKqwL6Sc3bI4WBwHaxwVDo/bNwMs0w\no8ngOs1jPd3LfQdfG/rE1NolpHm4LWqYj0D2zEGqozLXVBx2wiuwmm6OKX4U4EHR\nUwKax+VZYA+J9oFDN+kOy/yR+bKnOvg5eyOv2ZrK5BKceSBhDTOclMIWTL2cGxcL\njsq4N7fobs4TbwFPxRUi/T9ldXi0LXeGhTl9stImTtj3bL+4Y734TipvB5UvzCDK\nCkjjwEvD5MYdGDE=\n=uvIf\n-----END PGP PUBLIC KEY BLOCK-----\nEOF\n# fingerprint: E4CA86768F176AEB6C01554153AF8D7F149613B1\n```\n\nYou can choose between a RSA GPG key (default, like in the example above) or a\nCurve25519 based one by adding `--keytype Curve25519` like so:\n\n```console\n$ nix run github:Mic92/sops-nix#sops-init-gpg-key -- --hostname server01 --gpghome /tmp/newkey --keytype Curve25519\nYou can use the following command to save it to a file:\ncat \u003e server01.asc \u003c\u003cEOF\n-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmDMEY7dJExYJKwYBBAHaRw8BAQdAloRZFyqNh3nIDtyUQKaBSMJOtLkbNeg+4TPg\nBG5TduG0OG5peC1hLmhvbWUua3VldGVtZWllci5kZSA8cm9vdEBuaXgtYS5ob21l\nLmt1ZXRlbWVpZXIuZGU+iJMEExYKADsWIQREE2hPxiNijOo+CSmrLxbGte+J7wUC\nY7dJEwIbAwULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRCrLxbGte+J79LX\nAQDtLfQFDKm04ORIk28DrzTBbMTFQEW21dGBXk7ykBx4jQD/ZOnt1RPnB9mzMc8L\nwIS3oI8D9719DjoS9hrHnJ4xvge4OARjt0kTEgorBgEEAZdVAQUBAQdA0t1X35pN\nic+etscIIkHjKUwrXhbTgWrARgXUuEMwwz8DAQgHiHgEGBYKACAWIQREE2hPxiNi\njOo+CSmrLxbGte+J7wUCY7dJEwIbDAAKCRCrLxbGte+J7+0NAQCfj95TSyPEFKz3\neLJ1aCA1bZZV/rkhHd+OwX1MFL3mKQD9GMPgvMzDIoofycDzMY2ttJgkRJfq+zOZ\njuXFQdUkMgY=\n=pf3V\n-----END PGP PUBLIC KEY BLOCK-----\nEOF\nfingerprint: 4413684FC623628CEA3E0929AB2F16C6B5EF89EF\nF0477297E369CD1D189DD901278D1535AB473B9E\n```\n\nIn both cases, you must upload the GPG key directory `/tmp/newkey` onto the server.\nIf you uploaded it to `/var/lib/sops` than your sops configuration will look like this:\n\n```nix\n{\n  # Make sure that `/var/lib/sops` is owned by root and is not world-readable/writable\n  sops.gnupg.home = \"/var/lib/sops\";\n  # disable importing host ssh keys\n  sops.gnupg.sshKeyPaths = [];\n}\n```\n\nHowever be aware that this will also run GnuPG on your server including the\nGnuPG daemon. [GnuPG is in general not great software](https://latacora.micro.blog/2019/07/16/the-pgp-problem.html) and might break in\nhilarious ways. If you experience problems, you are on your own. If you want a\nmore stable and predictable solution go with SSH keys or one of the KMS services.\n\n\n## Share secrets between different users\n\nSecrets can be shared between different users by creating different files\npointing to the same sops key but with different permissions. In the following\nexample the `drone` secret is exposed as `/run/secrets/drone-server` for\n`drone-server` and as `/run/secrets/drone-agent` for `drone-agent`:\n\n```nix\n{\n  sops.secrets.drone-server = {\n    owner = config.systemd.services.drone-server.serviceConfig.User;\n    key = \"drone\";\n  };\n  sops.secrets.drone-agent = {\n    owner = config.systemd.services.drone-agent.serviceConfig.User;\n    key = \"drone\";\n  };\n}\n```\n\n## Migrate from pass/krops\n\nIf you have used [pass](https://www.passwordstore.org) before (e.g. in\n[krops](https://github.com/krebs/krops)) than you can use the following one-liner\nto convert all your secrets to a YAML structure:\n\n```console\n$ for i in *.gpg; do echo \"$(basename $i .gpg): |\\n$(pass $(dirname $i)/$(basename $i .gpg)| sed 's/^/  /')\"; done\n```\n\nCopy the output to the editor you have opened with sops.\n\n## Real-world examples\n\nThe [nix-community infra](https://github.com/nix-community/infra) makes extensive usage of sops-nix.\nEach host has a [secrets.yaml](https://github.com/nix-community/infra/tree/master/hosts/build01) containing secrets for the host.\nAlso Samuel Leathers explains his personal setup in this [blog article](https://samleathers.com/posts/2022-02-11-my-new-network-and-sops.html).\n\n## Known limitations\n\n### Initrd secrets\n\nsops-nix does not fully support initrd secrets.\nThis is because `nixos-rebuild switch` installs\nthe bootloader before running sops-nix's activation hook.  \nAs a workaround, it is possible to run `nixos-rebuild test`\nbefore `nixos-rebuild switch` to provision initrd secrets\nbefore actually using them in the initrd.\nIn the future, we hope to extend NixOS to allow keys to be\nprovisioned in the bootloader install phase.\n\n### Using secrets at evaluation time\n\nIt is not possible to use secrets at evaluation time of nix code. This is\nbecause sops-nix decrypts secrets only in the activation phase of nixos i.e. in\n`nixos-rebuild switch` on the target machine. If you rely on this feature for\nsome secrets, you should also include solutions that allow secrets to be stored\nsecurely in your version control, e.g.\n[git-agecrypt](https://github.com/vlaci/git-agecrypt). These types of solutions\ncan be used together with sops-nix.\n\n## Templates\n\nIf your setup requires embedding secrets within a configuration file, the `template` feature of `sops-nix` provides a seamless way to do this. \n\nHere's how to use it:\n\n1. **Define Your Secret**\n\n   Specify the secrets you intend to use. This will be encrypted and managed securely by `sops-nix`.\n\n   ```nix\n   {\n     sops.secrets.your-secret = { };\n   }\n   ```\n\n2. **Use Templates for Configuration with Secrets**\n\n   Create a template for your configuration file and utilize the placeholder where you'd like the secret to be inserted. \n   During the activation phase, `sops-nix` will substitute the placeholder with the actual secret content.\n\n   ```nix\n   {\n     sops.templates.\"your-config-with-secrets.toml\".content = ''\n       password = \"${config.sops.placeholder.your-secret}\"\n     '';\n   }\n   ```\n\n   You can also define ownership properties for the configuration file:\n\n   ```nix\n   { \n     sops.templates.\"your-config-with-secrets.toml\".owner = \"serviceuser\";\n   }\n   ```\n\n3. **Reference the Rendered Configuration in Services**\n\n   When defining a service (e.g., using `systemd`), refer to the rendered configuration (with secrets in place) by leveraging the `.path` attribute.\n\n   ```nix\n   {\n     systemd.services.myservice = {\n       # ... (any other service attributes)\n\n       serviceConfig = {\n         ExecStart = \"${pkgs.myservice}/bin/myservice --config ${config.sops.templates.\"your-config-with-secrets.toml\".path}\";\n         User = \"serviceuser\";\n       };\n     };\n   }\n   ```\n\n## Related projects\n\n- [agenix](https://github.com/ryantm/agenix): Similar features as sops-nix but\n  uses age.\n- [scalpel](https://github.com/polygon/scalpel): Provides a simple template\n  mechanism to inject secrets into configuration files in the nixos activation\n  phase\n\n\n# Need more commercial support?\n\n\nWe are building sops-nix very much as contributors to the community and are committed to keeping it open source.\n\nThat said, many of us that are contributing to sops-nix also work for consultancies. If you want to contact one of those for paid-for support setting up sops-nix in your infrastructure you can do so here:\n* [Numtide](https://numtide.com/contact)\n* [Helsinki Systems](https://helsinki-systems.de/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmic92%2Fsops-nix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmic92%2Fsops-nix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmic92%2Fsops-nix/lists"}