Building blocks for self-hosting with battery included.
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.
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:
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:
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:
outputs = inputs@{ self, nixpkgs, ... }: {
colmena = {
meta = {
nixpkgs = import inputs.nixpkgs {
system = "x86_64-linux";
};
specialArgs = inputs;
};
myserver = import ./machines/myserver.nix;
};
}
Now, what goes inside this ./machines/myserver.nix
file? Let's say you want to deploy Nextcloud,
you would use the nextcloud.nix
module from this repo as reference and have something like the following.
First, some common configuration:
imports = [
selfhostblocks.nixosModules.default
sops-nix.nixosModules.default
]
shb.ssl = {
enable = true;
domain = "example.com";
adminEmail = "[email protected]";
sopsFile = ./secrets/linode.yaml;
dnsProvider = "linode";
};
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.
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
};
First, use the same common configuration as above. Then add the SSO and LDAP providers:
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 = "[email protected]";
};
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
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
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
orjellyfin_admin
ldap group to be able to login, - all the required databases and secrets
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
$ nix run nixpkgs#colmena -- apply
"/nix/store/yyw9rgn8v5jrn4657vwpg01ydq0hazgx-nixos-system-baryum-23.11pre-git"
# Make some changes
$ nix run nixpkgs#colmena -- build
...
Built "/nix/store/16n1klx5cxkjpqhrdf0k12npx3vn5042-nixos-system-baryum-23.11pre-git"
$ 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
Also, in lieu of nix-diff
, a nice summary of version changes can be produced with:
nix run nixpkgs#nvd -- diff \
/nix/store/yyw9rgn8v5jrn4657vwpg01ydq0hazgx-nixos-system-baryum-23.11pre-git \
/nix/store/16n1klx5cxkjpqhrdf0k12npx3vn5042-nixos-system-baryum-23.11pre-git \
- Add examples that sets up instance in a VM.
- Do not depend on sops.
- Add more options to avoid hardcoding stuff.
- Make sure nginx gets reloaded when SSL certs gets updated.