2022-12-18 00:43:42 +01:00
# Self Host Blocks
2023-08-04 09:05:28 +02:00
<!-- toc:start -->
2023-11-16 21:44:19 +01:00
- [Supported Features ](#supported-features )
- [Repo layout ](#repo-layout )
- [How to Use ](#how-to-use )
- [Deploy a Nextcloud Instance ](#deploy-a-nextcloud-instance )
- [Deploy an hledger Instance with LDAP and SSO support ](#deploy-an-hledger-instance-with-ldap-and-sso-support )
- [Deploy a Jellyfin instance with LDAP and SSO support ](#deploy-a-jellyfin-instance-with-ldap-and-sso-support )
- [Tips ](#tips )
- [Run tests ](#run-tests )
- [Deploy using colmena ](#deploy-using-colmena )
- [Use a local version of selfhostblocks ](#use-a-local-version-of-selfhostblocks )
- [Diff changes ](#diff-changes )
- [What is deployed ](#what-is-deployed )
- [What will get deployed ](#what-will-get-deployed )
- [Get the full diff ](#get-the-full-diff )
- [Get version bumps ](#get-version-bumps )
- [Generate secret ](#generate-secret )
- [TODOs ](#todos )
- [Links that helped ](#links-that-helped )
2023-08-04 09:05:28 +02:00
<!-- toc:end -->
2023-02-20 05:50:39 +01:00
*Building blocks for self-hosting with battery included.*
2022-12-18 00:43:42 +01:00
2023-06-23 06:22:21 +02:00
SHB's (Self Host Blocks) goal is to provide a lower entry-bar for self-hosting. I intend to achieve
this by providing opinionated building blocks fitting together to self-host a wide range of
services. Also, the design will be extendable to allow users to add services not provided by SHB.
2023-07-30 07:26:32 +02:00
2023-11-14 09:14:56 +01:00
For each service, I intend to provide turn-key Nix options to setup:
- Access through a subdomain.
- HTTPS access.
- Backup.
- Single sign-on.
- LDAP user management.
2023-07-30 07:26:32 +02:00
## Supported Features
2023-11-14 09:14:56 +01:00
Currently supported services and features are:
2023-08-10 05:39:32 +02:00
- [X] Authelia as SSO provider.
- [X] Export metrics to Prometheus.
2023-07-30 07:26:32 +02:00
- [X] LDAP server through lldap, it provides a nice Web UI.
2023-07-31 02:44:50 +02:00
- [X] Administrative UI only accessible from local network.
2023-07-30 07:26:32 +02:00
- [X] Backup with Restic or BorgBackup
2023-09-23 09:04:01 +02:00
- [ ] UI for backups.
- [ ] Export metrics to Prometheus.
2023-11-07 05:34:32 +01:00
- [ ] Alert when backups fail or are not done on time.
2023-07-30 07:26:32 +02:00
- [X] Monitoring through Prometheus and Grafana.
- [X] Export systemd services status.
- [X] Reverse Proxy with Nginx.
- [ ] Export metrics to Prometheus.
2023-09-23 09:04:01 +02:00
- [ ] Log slow requests.
2023-07-30 07:26:32 +02:00
- [X] SSL support.
- [X] Backup support.
2023-11-07 04:47:31 +01:00
- [X] Vaultwarden
- [X] UI only accessible for `vaultwarden_user` LDAP group.
- [X] `/admin` only accessible for `vaultwarden_admin` LDAP group.
- [WIP] True SSO support, see [dani-garcia/vaultwarden/issues/246 ](https://github.com/dani-garcia/vaultwarden/issues/246 ). For now, Authelia protects access to the UI but you need to login afterwards to Vaultwarden. So there are two login required.
2023-07-30 07:26:32 +02:00
- [X] Nextcloud
- [ ] Export metrics to Prometheus.
2023-10-15 02:21:59 +02:00
- [ ] Export traces to Prometheus.
2023-07-30 07:26:32 +02:00
- [X] LDAP auth, unfortunately we need to configure this manually.
- [ ] SSO auth.
- [X] Backup support.
- [X] Home Assistant.
2023-08-04 09:04:37 +02:00
- [ ] Export metrics to Prometheus.
2023-08-05 20:50:29 +02:00
- [X] LDAP auth through `homeassistant_user` LDAP group.
2023-08-04 09:04:37 +02:00
- [ ] SSO auth.
- [X] Backup support.
- [X] Jellyfin
2023-07-30 07:26:32 +02:00
- [ ] Export metrics to Prometheus.
2023-08-05 20:50:29 +02:00
- [X] LDAP auth through `jellyfin_user` and `jellyfin_admin` LDAP groups.
2023-08-05 21:46:14 +02:00
- [X] SSO auth.
2023-07-30 07:26:32 +02:00
- [X] Backup support.
2023-09-03 00:00:41 +02:00
- [X] Hledger
- [ ] Export metrics to Prometheus.
- [X] LDAP auth through `hledger_user` LDAP group.
- [X] SSO auth.
- [ ] Backup support.
2023-09-23 09:04:01 +02:00
- [X] Database Postgres
- [ ] Slow log monitoring.
- [ ] Export metrics to Prometheus.
2023-11-07 05:34:32 +01:00
- [X] VPN tunnel
- [X] Arr suite
2023-11-15 21:44:47 +01:00
- [X] SSO auth (one account for all users).
2023-11-07 05:34:32 +01:00
- [X] VPN support.
2023-10-22 06:41:17 +02:00
- [X] Mount webdav folders
2023-11-05 04:30:01 +01:00
- [ ] Gitea to deploy
- [ ] Scrutiny to monitor hard drives health
- [ ] Export metrics to Prometheus.
2023-09-26 07:16:20 +02:00
2023-10-15 00:07:38 +02:00
## Repo layout
The top-level `flake.nix` just outputs a nixos module that gathers all other modules from `modules/` .
Some provided modules are low-level and some are high-level that re-use those low-level ones. For
example, the nextcloud module re-uses the backup and nginx ones.
## How to Use
You want to use this repo as a flake input to your own repo. The `inputs` field of your `flake.nix`
file in your repo should look like so:
```nix
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
sops-nix.url = "github:Mic92/sops-nix";
selfhostblocks.url = "github:ibizaman/selfhostblocks";
selfhostblocks.inputs.nixpkgs.follows = "nixpkgs";
selfhostblocks.inputs.sops-nix.follows = "sops-nix";
};
```
`sops-nix` is used to setup passwords and secrets. Currently `selfhostblocks` has a strong
dependency on it but I'm working on removing that so you could use any secret provider.
Also, if you ever want to hack on `selfhostblocks` yourself, you can clone it and then update the
`selfhostblocks` url to point to the absolute path of where you cloned it:
```nix
selfhostblocks.url = "/home/me/projects/selfhostblocks";
```
Now, how you actually deploy using selfhostblocks depends on what system you chose. If you use colmena, this is what your `outputs` field should look like:
```nix
outputs = inputs@{ self, nixpkgs, ... }: {
colmena = {
meta = {
nixpkgs = import inputs.nixpkgs {
system = "x86_64-linux";
};
specialArgs = inputs;
};
myserver = import ./machines/myserver.nix;
};
}
```
### Deploy a Nextcloud Instance
Now, what goes inside this `./machines/myserver.nix` file? Let's say you want to deploy Nextcloud,
2023-11-05 13:46:34 +01:00
you would use the [`nextcloud.nix` ](./modules/nextcloud.nix ) module from this repo as reference and
have something like the following.
2023-10-15 00:07:38 +02:00
First, some common configuration:
```nix
imports = [
2023-11-05 04:30:17 +01:00
selfhostblocks.nixosModules.x86_64-linux.default
2023-10-15 00:07:38 +02:00
sops-nix.nixosModules.default
]
shb.ssl = {
enable = true;
domain = "example.com";
adminEmail = "me@example.com";
sopsFile = ./secrets/linode.yaml;
dnsProvider = "linode";
};
```
2023-11-05 13:46:34 +01:00
This will import the NixOS module provided by this repository as well as the `sops-nix` module,
needed to store secrets. It then enables SSL support.
2023-10-15 00:07:38 +02:00
Then, the configuration for Nextcloud which sets up:
- the nginx reverse proxy to listen on requests for the `nextcloud.example.com` domain,
- backup of the config folder and the data folder,
- an onlyoffice instance listening at `oo.example.com` that only listens on the local
nextwork; you still need to setup the onlyoffice plugin in Nextcloud,
- and all the required databases and secrets.
```nix
shb.nextcloud = {
enable = true;
domain = "example.com";
subdomain = "nextcloud";
sopsFile = ./secrets/nextcloud.yaml;
localNetworkIPRange = "192.168.1.0/24";
debug = false;
};
services.nextcloud = {
datadir = "/srv/nextcloud";
poolSettings = {
"pm" = "dynamic";
"pm.max_children" = 120;
"pm.start_servers" = 12;
"pm.min_spare_servers" = 6;
"pm.max_spare_servers" = 18;
};
};
shb.backup.instances.nextcloud = {
backend = "restic";
keySopsFile = ./secrets/backup.yaml;
repositories = [
"/srv/backup/restic/nextcloud"
"s3:s3.us-west-000.backblazeb2.com/myserver-backup/nextcloud"
];
retention = {
keep_within = "1d";
keep_hourly = 24;
keep_daily = 7;
keep_weekly = 4;
keep_monthly = 6;
};
consistency = {
repository = "2 weeks";
archives = "1 month";
};
environmentFile = true; # Needed for s3
};
```
### Deploy an hledger Instance with LDAP and SSO support
First, use the same common configuration as above. Then add the SSO and LDAP providers:
```nix
shb.ldap = {
enable = true;
domain = "example.com";
subdomain = "ldap";
dcdomain = "dc=example,dc=com";
sopsFile = ./secrets/ldap.yaml;
localNetworkIPRange = "192.168.1.0/24";
};
shb.backup.instances.lldap = # Same as for the Nextcloud one above
shb.authelia = {
enable = true;
domain = "example.com";
subdomain = "authelia";
sopsFile = ./secrets/authelia.yaml;
ldapEndpoint = "ldap://127.0.0.1:3890";
dcdomain = config.shb.ldap.dcdomain;
smtpHost = "smtp.mailgun.org";
smtpPort = 587;
smtpUsername = "postmaster@mg.example.com";
};
```
Finally, the hledger specific part which sets up:
- the nginx reverse proxy to listen on requests for the `hledger.example.com` domain,
- backup of everything,
- only allow users of the hledger_user to be able to login,
- all the required databases and secrets
```nix
shb.hledger = {
enable = true;
subdomain = "hledger";
domain = "example.com";
oidcEndpoint = "https://authelia.example.com";
localNetworkIPRange = "192.168.1.0/24";
};
shb.backup.instances.hledger = # Same as the examples above
```
### Deploy a Jellyfin instance with LDAP and SSO support
First, use the same common configuration as for the Nextcloud example and the SSO and LDAP
configuration than for the hledger example. Then, the jellyfin specific part which sets up :
- the nginx reverse proxy to listen on requests for the `jellyfin.example.com` domain,
- backup of everything,
- only allow users of the `jellyfin_user` or `jellyfin_admin` ldap group to be able to login,
- all the required databases and secrets
```nix
shb.jellyfin = {
enable = true;
domain = "example.com";
subdomain = "jellyfin";
sopsFile = ./secrets/jellyfin.yaml;
ldapHost = "127.0.0.1";
ldapPort = 3890;
dcdomain = config.shb.ldap.dcdomain;
oidcEndpoint = "https://authelia.example.com";
oidcClientID = "jellyfin";
oidcAdminUserGroup = "jellyfin_admin";
oidcUserGroup = "jellyfin_user";
};
shb.backup.instances.jellyfin = # Same as the examples above
```
2023-09-26 07:16:20 +02:00
## Tips
2023-11-06 04:55:29 +01:00
### Run tests
```bash
$ nix flake check
```
2023-10-15 00:07:38 +02:00
### Deploy using colmena
2023-09-26 07:54:46 +02:00
```bash
$ nix run nixpkgs#colmena -- apply
```
2023-11-06 04:45:28 +01:00
### Use a local version of selfhostblocks
This works with any flake input you have. Either, change the `.url` field directly in you `flake.nix` :
```nix
selfhostblocks.url = "/home/me/projects/selfhostblocks";
```
Or override on the command line:
```bash
nix run nixpkgs#colmena --override-input selfhostblocks ../selfhostblocks -- apply
```
2023-09-26 07:16:20 +02:00
### Diff changes
2023-11-06 04:45:28 +01:00
First, you must know what to compare. You need to know the path to the nix store of what is already deployed and to what you will deploy.
#### What is deployed
To know what is deployed, either just stash the changes you made and run `build` :
```bash
$ nix run nixpkgs#colmena -- build
...
Built "/nix/store/yyw9rgn8v5jrn4657vwpg01ydq0hazgx-nixos-system-baryum-23.11pre-git"
```
Or ask the target machine:
```bash
$ nix run nixpkgs#colmena -- exec -v readlink -f /run/current-system
baryum | /nix/store/77n1hwhgmr9z0x3gs8z2g6cfx8gkr4nm-nixos-system-baryum-23.11pre-git
```
#### What will get deployed
2023-09-26 07:16:20 +02:00
2023-11-06 04:45:28 +01:00
Assuming you made some changes, then instead of deploying with `apply` , just `build` :
2023-09-26 07:16:20 +02:00
2023-11-06 04:45:28 +01:00
```bash
2023-09-26 07:16:20 +02:00
$ nix run nixpkgs#colmena -- build
...
Built "/nix/store/16n1klx5cxkjpqhrdf0k12npx3vn5042-nixos-system-baryum-23.11pre-git"
2023-11-06 04:45:28 +01:00
```
#### Get the full diff
2023-09-26 07:16:20 +02:00
2023-11-06 04:45:28 +01:00
With `nix-diff` :
```
2023-09-26 07:16:20 +02:00
$ nix run nixpkgs#nix-diff -- \
/nix/store/yyw9rgn8v5jrn4657vwpg01ydq0hazgx-nixos-system-baryum-23.11pre-git \
/nix/store/16n1klx5cxkjpqhrdf0k12npx3vn5042-nixos-system-baryum-23.11pre-git \
--color always | less
```
2023-09-27 22:28:25 +02:00
2023-11-06 04:45:28 +01:00
#### Get version bumps
A nice summary of version changes can be produced with:
2023-09-27 22:28:25 +02:00
```bash
nix run nixpkgs#nvd -- diff \
/nix/store/yyw9rgn8v5jrn4657vwpg01ydq0hazgx-nixos-system-baryum-23.11pre-git \
/nix/store/16n1klx5cxkjpqhrdf0k12npx3vn5042-nixos-system-baryum-23.11pre-git \
```
2023-10-01 00:49:42 +02:00
2023-11-07 07:53:23 +01:00
### Generate secret
```bash
$ nix run nixpkgs#openssl -- rand -hex 64
```
2023-10-01 00:49:42 +02:00
## TODOs
2023-10-15 00:07:38 +02:00
- [ ] Add examples that sets up instance in a VM.
- [ ] Do not depend on sops.
- [ ] Add more options to avoid hardcoding stuff.
2023-10-01 00:49:42 +02:00
- [ ] Make sure nginx gets reloaded when SSL certs gets updated.
2023-11-15 21:46:53 +01:00
- [ ] Better backup story by taking optional LVM snapshot before backing up.
2023-11-15 21:53:50 +01:00
## Links that helped:
While creating an XML config generator for Radarr:
- https://stackoverflow.com/questions/4906977/how-can-i-access-environment-variables-in-python
- https://stackoverflow.com/questions/7771011/how-can-i-parse-read-and-use-json-in-python
- https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/writers/scripts.nix
- https://stackoverflow.com/questions/43837691/how-to-package-a-single-python-script-with-nix
- https://ryantm.github.io/nixpkgs/languages-frameworks/python/#python
- https://ryantm.github.io/nixpkgs/hooks/python/#setup-hook-python
- https://ryantm.github.io/nixpkgs/builders/trivial-builders/
- https://discourse.nixos.org/t/basic-flake-run-existing-python-bash-script/19886
- https://docs.python.org/3/tutorial/inputoutput.html
- https://pypi.org/project/json2xml/
- https://www.geeksforgeeks.org/serialize-python-dictionary-to-xml/
- https://nixos.org/manual/nix/stable/language/builtins.html#builtins-toXML
- https://github.com/NixOS/nixpkgs/blob/master/pkgs/pkgs-lib/formats.nix