# Usage {#usage} ## Flake {#usage-flake} Self Host Blocks is available as a flake. To use it in your project, add the following flake input: ```nix inputs.selfhostblocks.url = "github:ibizaman/selfhostblocks"; ``` Then, in your `nixosConfigurations`, import the module with: ```nix imports = [ inputs.selfhostblocks.nixosModules.x86_64-linux.default ]; ``` You can also use the public cache as a substituter with: ```nix nix.settings.trusted-public-keys = [ "selfhostblocks.cachix.org-1:H5h6Uj188DObUJDbEbSAwc377uvcjSFOfpxyCFP7cVs=" ]; nix.settings.substituters = [ "https://selfhostblocks.cachix.org" ]; ``` For now, Self Host Blocks has a hard dependency on `sops-nix`. I am [working on removing that](https://github.com/ibizaman/selfhostblocks/issues/24) so you can use any secrets manager you want. Until then, you also need to import the `sops-nix` module: ```nix imports = [ inputs.selfhostblocks.inputs.sops-nix.nixosModules.default ]; ``` Self Host Blocks provides its own `nixpkgs` input so both can be updated in lock step, ensuring maximum compatibility. It is recommended to use the following `nixpkgs` as input for your deployments: ```nix inputs.selfhostblocks.inputs.nixpkgs ``` Advanced users can if they wish use a version of `nixpkgs` of their choosing but then we cannot guarantee Self Host Block won't use a non-existing option from `nixpkgs`. To avoid manually updating the `nixpkgs` version, the [GitHub repository][1] for Self Host Blocks tries to update the `nixpkgs` input daily, verifying all tests pass before accepting this new `nixpkgs` version. The setup is explained in [this blog post][2]. [1]: https://github.com/ibizaman/selfhostblocks [2]: https://blog.tiserbox.com/posts/2023-12-25-automated-flake-lock-update-pull-requests-and-merging.html ## Example Deployment with Nixos-Rebuild {#usage-example-nixosrebuild} The following snippets show how to deploy Self Host Blocks using the standard deployment system `nixos-rebuild`. ```nix { inputs = { selfhostblocks.url = "github:ibizaman/selfhostblocks"; }; outputs = { self, selfhostblocks }: { nixosConfigurations = { machine = selfhostblocks.inputs.nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ selfhostblocks.nixosModules.${system}.default ]; # Machine specific configuration goes here. }; }; }; } ``` The above snippet is very minimal as it assumes you have only one machine to deploy to, so `nixpkgs` is defined exclusively by the `selfhostblocks.inputs.nixpkgs` input. If some machines are not using Self Host Blocks, you can do the following: ```nix { inputs = { selfhostblocks.url = "github:ibizaman/selfhostblocks"; }; outputs = { self, selfhostblocks }: { nixosConfigurations = { machine1 = nixpkgs.lib.nixosSystem { }; machine2 = selfhostblocks.inputs.nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ selfhostblocks.nixosModules.${system}.default ]; # Machine specific configuration goes here. }; }; }; } ``` ## Example Deployment With Colmena {#usage-example-colmena} The following snippets show how to deploy Self Host Blocks using the deployment system [Colmena][3]. [3]: https://colmena.cli.rs ```nix { inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; selfhostblocks.url = "github:ibizaman/selfhostblocks"; }; outputs = { self, selfhostblocks }: { colmena = let system = "x86_64-linux"; in { meta = { nixpkgs = import selfhostblocks.inputs.nixpkgs { inherit system; }; }; machine = { selfhostblocks, ... }: { imports = [ selfhostblocks.nixosModules.${system}.default ]; # Machine specific configuration goes here. }; }; }; } ``` The above snippet is very minimal as it assumes you have only one machine to deploy to, so `nixpkgs` is defined exclusively by the `selfhostblocks` input. It is more likely that you have multiple machines, in this case you can use the `colmena.meta.nodeNixpkgs` option: ```nix { inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; selfhostblocks.url = "github:ibizaman/selfhostblocks"; }; outputs = { self, selfhostblocks }: { colmena = { let system = "x86_64-linux"; in { meta = nixpkgs = import nixpkgs { inherit system; }; nodeNixpkgs = { machine2 = import selfhostblocks.inputs.nixpkgs { inherit system; }; }; }; machine1 = ...; machine2 = { selfhostblocks, ... }: { imports = [ selfhostblocks.nixosModules.${system}.default ]; # Machine specific configuration goes here. }; }; }; } ``` In the above snippet, `machine1` will use the `nixpkgs` version from your inputs while `machine2` will use the `nixpkgs` version from `selfhostblocks`. ## Secrets with sops-nix {#usage-secrets} This section complements the official [sops-nix](https://github.com/Mic92/sops-nix) guide. Managing secrets is an important aspect of deploying. You cannot store your secrets in nix directly because they get stored unencrypted and you don't want that. We need to use another system that encrypts secrets when storing in the nix store and then decrypts them on the target host upon system activation. `sops-nix` is one of such system. Sops-nix works by encrypting the secrets file with at least 2 keys. Your private key and a private key from the target host. This way, you can edit the secrets and the target host can decrypt the secrets. Separating the keys this way is good practice because it reduces the impact of having one being compromised. One way to setup secrets management using `sops-nix`: 1. Create your own private key that will be located in `keys.txt`. The public key will be printed on stdout. ```bash $ nix shell nixpkgs#age --command age-keygen -o keys.txt Public key: age1algdv9xwjre3tm7969eyremfw2ftx4h8qehmmjzksrv7f2qve9dqg8pug7 ``` 2. Get the target host's public key. We will use the key derived from the ssh key of the host. ```bash $ nix shell nixpkgs#ssh-to-age --command \ sh -c 'ssh-keyscan -t ed25519 -4 | ssh-to-age' # localhost:2222 SSH-2.0-OpenSSH_9.6 age13wgyyae8epyw894ugd0rjjljh0rm98aurvzmsapcv7d852g9r5lq0pqfx8 ``` 3. Create a `sops.yaml` file that explains how sops-nix should encrypt the - yet to be created - `secrets.yaml` file. You can be creative here, but a basic snippet is: ```bash keys: - &me age1algdv9xwjre3tm7969eyremfw2ftx4h8qehmmjzksrv7f2qve9dqg8pug7 - &target age13wgyyae8epyw894ugd0rjjljh0rm98aurvzmsapcv7d852g9r5lq0pqfx8 creation_rules: - path_regex: secrets.yaml$ key_groups: - age: - *me - *target ``` 4. Create a `secrets.yaml` file that will contain the encrypted secrets as a Yaml file: ```bash $ SOPS_AGE_KEY_FILE=keys.txt nix run --impure nixpkgs#sops -- \ secrets.yaml ``` This will open your preferred editor. An example of yaml file is the following (secrets are elided for brevity): ```yaml nextcloud: adminpass: 43bb4b... onlyoffice: jwt_secret: 3a10fce3... ``` The actual file on your filesystem will look like so, again with data elided: ```yaml nextcloud: adminpass: ENC[AES256_GCM,data:Tt99...GY=,tag:XlAqRYidkOMRZAPBsoeEMw==,type:str] onlyoffice: jwt_secret: ENC[AES256_GCM,data:f87a...Yg=,tag:Y1Vg2WqDnJbl1Xg2B6W1Hg==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: - recipient: age1algdv9xwjre3tm7969eyremfw2ftx4h8qehmmjzksrv7f2qve9dqg8pug7 enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdl...6g== -----END AGE ENCRYPTED FILE----- - recipient: age13wgyyae8epyw894ugd0rjjljh0rm98aurvzmsapcv7d852g9r5lq0pqfx8 enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdl...RA== -----END AGE ENCRYPTED FILE----- lastmodified: "2024-01-28T06:07:02Z" mac: ENC[AES256_GCM,data:lDJh...To=,tag:Opon9lMZBv5S7rRhkGFuQQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.8.1 ``` To actually create random secrets, you can use: ```bash $ nix run nixpkgs#openssl -- rand -hex 64 ``` 5. Use `sops-nix` module in nix: ```bash imports = [ selfhostblocks.inputs.sops-nix.nixosModules.default ]; ``` 6. Reference the secrets in nix: ```nix shb.nextcloud.adminPassFile = config.sops.secrets."nextcloud/adminpass".path; sops.secrets."nextcloud/adminpass" = { sopsFile = ./secrets.yaml; mode = "0440"; owner = "nextcloud"; group = "nextcloud"; restartUnits = [ "phpfpm-nextcloud.service" ]; }; ```