1
0
Fork 0

reorganize home assistant demo

This commit is contained in:
Pierre Penninckx 2023-11-19 23:11:03 -08:00 committed by GitHub
parent ea08aec4a7
commit 5f4019a34c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 240 additions and 190 deletions

16
.github/workflows/demo.yml vendored Normal file
View file

@ -0,0 +1,16 @@
name: "Demo"
on:
pull_request:
push:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
- run: |
for d in ./demo;
do (cd "$d"; nix flake check)
done

View file

@ -166,7 +166,13 @@ imports = [
]
```
For how to deploy services, check the examples below.
For how to configure the services, check the sections below.
## Demos
Demos that start and deploy on a Virtual Machine on your computer are located under the
[demo](./demo/) folder. These show the onboarding experience you would get if you deployed
selfhostblocks on your own server.
## Examples

View file

@ -0,0 +1,195 @@
# Home Assistant Demo
The [`flake.nix`](./flake.nix) file sets up Home Assistant server that uses a LDAP server to
setup users in only about [15 lines](./flake.nix#L29-L45) of related code.
This guide will show how to deploy this setup to a Virtual Machine, like showed
[here](https://nixos.wiki/wiki/NixOS_modules#Developing_modules), in 5 commands.
## Deploy to the VM
Build VM with:
```bash
nixos-rebuild build-vm-with-bootloader --fast -I nixos-config=./configuration.nix -I nixpkgs=.
```
Start VM with (this call is blocking):
```bash
QEMU_NET_OPTS="hostfwd=tcp::2222-:2222,hostfwd=tcp::8080-:80" ./result/bin/run-nixos-vm
```
With the VM started, print the VM's public age key with the following command. The value you need is
the one staring with `age`.
```bash
$ nix shell nixpkgs#ssh-to-age --command sh -c 'ssh-keyscan -p 2222 -4 localhost | ssh-to-age'
# localshost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
skipped key: got ssh-rsa key type, but only ed25519 keys are supported
age1l9dyy02qhlfcn5u9s4y2vhsvjtxj2c9avrpat6nvjd6rjar3tflq66jtz0
```
Now, make the `secrets.yaml` file decryptable in the VM.
```bash
SOPS_AGE_KEY_FILE=keys.txt nix run --impure nixpkgs#sops -- \
--config sops.yaml -r -i \
--add-age age1l9dyy02qhlfcn5u9s4y2vhsvjtxj2c9avrpat6nvjd6rjar3tflq66jtz0 \
secrets.yaml
```
Finally, deploy with:
```bash
SSH_CONFIG_FILE=ssh_config nix run nixpkgs#colmena --impure -- apply
```
This step will require you to accept the host's fingerprint. The deploy will take a few minutes the first time and subsequent deploys will take around 15 seconds.
## Access Home Assistant Through Your Browser
Add the following entry to your `/etc/hosts` file:
```nix
networking.hosts = {
"127.0.0.1" = [ "ha.example.com" "ldap.example.com" ];
};
```
Which produces:
```bash
$ cat /etc/hosts
127.0.0.1 ha.example.com ldap.example.com
```
Go to [http://ldap.example.com:8080](http://ldap.example.com:8080) and login with:
- username: `admin`
- password: the value of the field `lldap.user_password` in the `secrets.yaml` file which is.
Create the group `homeassistant_user` and a user assigned to that group.
Go to [http://ha.example.com:8080](http://ha.example.com:8080) and login with the
user and password you just created above.
## In More Details
### Files
- [`flake.nix`](./flake.nix): nix entry point, defines one target host for
[colmena](https://colmena.cli.rs) to deploy to as well as the selfhostblock's config for
setting up the home assistant server paired with the LDAP server.
- [`configuration.nix`](./configuration.nix): defines all configuration required for colmena
to deploy to the VM. The file has comments if you're interested.
- [`hardware-configuration.nix`](./hardware-configuration.nix): defines VM specific layout.
This was generated with nixos-generate-config on the VM.
- Secrets related files:
- [`keys.txt`](./keys.txt): your private key for sops-nix, allows you to edit the `secrets.yaml`
file. This file should never be published but here I did it for convenience, to be able to
deploy to the VM in less steps.
- [`secrets.yaml`](./secrets.yaml): encrypted file containing required secrets for Home Assistant
and the LDAP server. This file can be publicly accessible.
- [`sops.yaml`](./sops.yaml): describes how to create the `secrets.yaml` file. Can be publicly
accessible.
- SSH related files:
- [`sshkey(.pub)`](./sshkey): your private and public ssh keys. Again, the private key should usually not
be published as it is here but this makes it possible to deploy to the VM in less steps.
- [`ssh_config`](./ssh_config): the ssh config allowing you to ssh into the VM by just using the
hostname `example`. Usually you would store this info in your `~/.ssh/config` file but it's
provided here to avoid making you do that.
### Virtual Machine
_More info about the VM._
We use `build-vm-with-bootloader` instead of just `build-vm` as that's the only way to deploy to the VM.
The VM's User and password are both `nixos`, as setup in the [`configuration.nix`](./configuration.nix) file under
`user.users.nixos.initialPassword`.
You can login with `ssh -F ssh_config example`. You just need to accept the fingerprint.
### Secrets
_More info about the secrets._
The private key in the `keys.txt` file is created with:
```bash
$ nix shell nixpkgs#age --command age-keygen -o keys.txt
Public key: age1algdv9xwjre3tm7969eyremfw2ftx4h8qehmmjzksrv7f2qve9dqg8pug7
```
We use the printed public key in the `admin` field in `sops.yaml` file.
The `secrets.yaml` file must follow the format:
```yaml
home-assistant: |
name: "My Instance"
country: "US"
latitude_home: "0.100"
longitude_home: "-0.100"
time_zone: "America/Los_Angeles"
unit_system: "metric"
lldap:
user_password: XXX...
jwt_secret: YYY...
```
You can generate random secrets with:
```bash
$ nix run nixpkgs#openssl -- rand -hex 64
```
#### Why do we need the VM's public key
The [`sops.yaml`](./sops.yaml) file describes what private keys can decrypt and encrypt the
[`secrets.yaml`](./secrets.yaml) file containing the application secrets. Usually, you will create and add
secrets to that file and when deploying, it will be decrypted and the secrets will be copied
in the `/run/secrets` folder on the VM. We thus need one private key for you to edit the
[`secrets.yaml`](./secrets.yaml) file and one in the VM for it to decrypt the secrets.
Your private key is already pre-generated in this repo, it's the [`sshkey`](./sshkey) file. But when
creating the VM in the step above, a new private key and its accompanying public key were
automatically generated under `/etc/ssh/ssh_host_ed25519_key` in the VM. We just need to get the
public key and add it to the `secrets.yaml` which we did in the Deploy section.
To open the `secrets.yaml` file and optionnally edit it, run:
```bash
SOPS_AGE_KEY_FILE=keys.txt nix run --impure nixpkgs#sops -- \
--config sops.yaml \
secrets.yaml
```
### SSH
The private and public ssh keys were created with:
```bash
ssh-keygen -t ed25519 -f sshkey
```
You don't need to copy over the ssh public key over to the VM as we set the `keyFiles` option which copies the public key when the VM gets created.
This allows us also to disable ssh password authentication.
For reference, here is what you would need to do if you didn't use the option:
```bash
$ nix shell nixpkgs#openssh --command ssh-copy-id -i sshkey -F ssh_config example
```
### Deploy
If you get a NAR hash mismatch error like herunder, you need to run `nix flake lock --update-input selfhostblocks`.
```
error: NAR hash mismatch in input ...
```

View file

@ -20,20 +20,29 @@
# Options above are needed to deploy in a VM.
# As we intend to run this example using `nixos-rebuild build-vm`, we need to setup the user
# ourselves, see https://nixos.wiki/wiki/NixOS:nixos-rebuild_build-vm
users.users.nixos = {
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Used by colmena to know which target host to deploy to.
deployment = {
targetHost = "example";
targetPort = 2222;
targetUser = "nixos";
};
# We need to create the user we will deploy with.
users.users.${config.deployment.targetUser} = {
isNormalUser = true;
extraGroups = [ "wheel" ]; # Enable sudo for the user.
initialPassword = "nixos";
# With this option, you don't need to use ssh-copy-id.
# With this option, you don't need to use ssh-copy-id to copy the public ssh key to the VM.
openssh.authorizedKeys.keyFiles = [
./sshkey.pub
];
};
# The user we're deploying with must be able to run sudo without password.
security.sudo.extraRules = [
{ users = [ "nixos" ];
{ users = [ config.deployment.targetUser ];
commands = [
{ command = "ALL";
options = [ "NOPASSWD" ];
@ -42,15 +51,16 @@
}
];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Needed to allow the user we're deploying with to write to the nix store.
nix.settings.trusted-users = [
"nixos"
config.deployment.targetUser
];
# We need to enable the ssh daemon to be able to deploy.
services.openssh = {
enable = true;
ports = [ 2222 ];
ports = [ config.deployment.targetPort ];
permitRootLogin = "no";
passwordAuthentication = true;
passwordAuthentication = false;
};
}

View file

@ -20,22 +20,12 @@
};
myserver = { config, ... }: {
deployment = {
targetHost = "example";
targetPort = 2222;
targetUser = "nixos";
};
imports = [
./configuration.nix
sops-nix.nixosModules.default
selfhostblocks.nixosModules.x86_64-linux.default
];
# Set to true for more debug info with `journalctl -f -u nginx`.
shb.nginx.accessLog = true;
shb.nginx.debugLog = true;
shb.ldap = {
enable = true;
domain = "example.com";
@ -54,10 +44,9 @@
sopsFile = ./secrets.yaml;
};
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.trusted-users = [
"nixos"
];
# Set to true for more debug info with `journalctl -f -u nginx`.
shb.nginx.accessLog = false;
shb.nginx.debugLog = false;
};
};
};

View file

@ -1,9 +1,7 @@
keys:
- &admin age1algdv9xwjre3tm7969eyremfw2ftx4h8qehmmjzksrv7f2qve9dqg8pug7
- &vm age18jrfv0ndtrad7ee4dzdfhhuca4wuce059txltdaxuxcnjkc37s5qj9mapm
creation_rules:
- path_regex: secrets.yaml$
key_groups:
- age:
- *admin
- *vm

View file

@ -1,164 +0,0 @@
# Home Assistant Example
This `flake.nix` file sets up Home Assistant server that uses a LDAP server to
setup users with only about [15 lines](./flake.nix#L39-L55) of related code.
This guide will show how to deploy this setup to a Virtual Machine, like showed
[here](https://nixos.wiki/wiki/NixOS_modules#Developing_modules), in 5 commands.
## Launch VM
Build VM with:
```bash
nixos-rebuild build-vm-with-bootloader --fast -I nixos-config=./configuration.nix -I nixpkgs=.
```
Start VM with (this call is blocking):
```bash
QEMU_NET_OPTS="hostfwd=tcp::2222-:2222,hostfwd=tcp::8080-:80" ./result/bin/run-nixos-vm
```
User and password are both `nixos`, as setup in the [`configuration.nix`](./configuration.nix) file under
`user.users.nixos.initialPassword`.
You can login with `ssh -F ssh_config example`. You just need to accept the fingerprint.
## Make VM able to decrypt the secrets.yaml file
The [`sops.yaml`](./sops.yaml) file describes what private keys can decrypt and encrypt the
[`secrets.yaml`](./secrets.yaml) file containing the application secrets. Usually, you will add
secrets to that secrets file and when deploying, it will be decrypted and the secrets will be copied
in the `/run/secrets` folder on the VM. We thus need one private key for you to edit the
[`secrets.yaml`](./secrets.yaml) file and one in the VM for it to decrypt the secrets.
Your private key is already pre-generated in this repo, it's the [`sshkey`](./sshkey) file. But when
creating the VM in the step above, a new private key and its accompanying public key were
automatically generated under `/etc/ssh/ssh_host_ed25519_key` in the VM. We just need to get the
public key.
With the VM started, print the VM's public age key with the following command. The value you need is
the one staring with `age`.
```bash
$ nix shell nixpkgs#ssh-to-age --command sh -c 'ssh-keyscan -p 2222 -4 localhost | ssh-to-age'
# localshost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
skipped key: got ssh-rsa key type, but only ed25519 keys are supported
age1l9dyy02qhlfcn5u9s4y2vhsvjtxj2c9avrpat6nvjd6rjar3tflq66jtz0
```
Now, make the `secrets.yaml` file decryptable in the VM.
```bash
SOPS_AGE_KEY_FILE=keys.txt nix run --impure nixpkgs#sops -- \
--config sops.yaml -r -i \
--add-age age1l9dyy02qhlfcn5u9s4y2vhsvjtxj2c9avrpat6nvjd6rjar3tflq66jtz0 \
secrets.yaml
```
Later on, when the server is deployed, you will need to login to the LDAP server with the admin account.
You can find the secret `lldap.user_password` field in the [`secrets.yaml`](./secrets.yaml) file. To open it, run:
```bash
SOPS_AGE_KEY_FILE=keys.txt nix run --impure nixpkgs#sops -- \
--config sops.yaml \
secrets.yaml
```
## Deploy
Now, deploy with:
```bash
SSH_CONFIG_FILE=ssh_config nix run nixpkgs#colmena --impure -- apply
```
Took a few minutes for first deploy on my machine. Next deploys take about 12 seconds.
## Access apps through your browser
Add the following entry to your `/etc/hosts` file:
```nix
networking.hosts = {
"127.0.0.1" = [ "ha.example.com" "ldap.example.com" ];
};
```
Which produces:
```bash
$ cat /etc/hosts
127.0.0.1 ha.example.com ldap.example.com
```
Go to [http://ldap.example.com:8080](http://ldap.example.com:8080) and login with:
- username: `admin`
- password: the value of the field `lldap.user_password` in the `secrets.yaml` file.
Create the group `homeassistant_user` and a user assigned to that group.
Go to [http://ha.example.com:8080](http://ha.example.com:8080) and login with the user and password you just created above.
## Prepare the VM
This section documents how the various files were created to provide the nearly out of the box
experience described in the previous section. I need to clean this up a bit.
### Private and Public Key
Create the private key in the `keys.txt` file and print the public key used for `admin`:
```bash
$ nix shell nixpkgs#age --command age-keygen -o keys.txt
Public key: age1algdv9xwjre3tm7969eyremfw2ftx4h8qehmmjzksrv7f2qve9dqg8pug7
```
Update `admin` and `vm` keys in `sops.yaml`.
Then, you can create the secrets.yaml with:
That file must follow the format:
```yaml
home-assistant: |
name: "My Instance"
country: "US"
latitude_home: "0.100"
longitude_home: "-0.100"
time_zone: "America/Los_Angeles"
unit_system: "metric"
lldap:
user_password: XXX...
jwt_secret: YYY...
```
You can generate secrets with:
```bash
$ nix run nixpkgs#openssl -- rand -hex 64
```
TODO: add instructions to create ssh private and public key:
```bash
```
You don't need to copy over the ssh public key with the following command as we set the `keyFiles` option. I still leave it here for reference.
```bash
$ nix shell nixpkgs#openssh --command ssh-copy-id -i sshkey -F ssh_config example
```
### Deploy
If you get a NAR hash mismatch error like so, you need to run `nix flake lock --update-input selfhostblocks`:
```
error: NAR hash mismatch in input ...
```