!Github: This repository is a representation of my server configuration, intended for viewing only. It will not work because secrets have been filtered out.
This project has been migrated to clan.lol: https://git.clan.lol/dafitt/schallerclan
| Servers | Description | Software |
|---|---|---|
| adguardhome🔗 | DNS Blocker. | Adguard Home |
| bitwarden🔗 | Password Manager. | Vaultwarden |
| DavidCAL🔗 | Calendar & Address book. | Radicale |
| DavidSYNC🔗 | File syncronization. | Syncthing |
| forgejo🔗 | Private GitHub. | Forgejo |
| haproxy-* | Reverse Proxy and Load Balancer. | HAProxy |
| homepage-*🔗 | Homepage / Dashboard. | homepage |
| idm🔗 | Kanidm is a modern and simple identity management platform written in rust. | Kanidm |
| mail🔗 | Mailserver. | Simple NixOS Mailserver |
| MichiSHARE | File share. | Samba |
| satisfactory | A first-person open-world factory building game. | nekowinston/satisfactory-server-flake |
| searx🔗 | Recursive Web Search Engine. | SearXNG |
| unbound | Recursive & authoritative DNS. | Unbound |
| uptimekuma🔗 | A fancy self-hosted monitoring tool. | Uptime Kuma |
| wireguard-* | VPN. | WireGuard |
| Hosts | Used for/as |
|---|---|
| barebonej3160 | Gateway, Subnetting, Routing, Firewall, DNS, VPN |
| minisforumhm80 | Always-on host for lightweight containers and experimentation. |
Some words on networking, since networking is hard.
Read the Networkstructure first.
We need to declare our network with the schallernetz.networking-option. See modules/nixos/networking/default.nix for available options.
My network options like schallernetz.networking.domain, schallernetz.networking.ip6 or schallernetz.networking.subnets must be set the same for every server host in this network. So I would recommend to put those options into a file like e.g. systems/global-configuration.nix and import this file to every server host with imports = [../../global-configuration.nix];.
Physical interfaces: Since physical interfaces are always different, it makes no sense to declare them in a module or globally. So they must be declared in systems/. An example:
systemd.network.networks = {
"30-enp4s0" = {
matchConfig.Name = "enp4s0";
linkConfig.RequiredForOnline = "enslaved";
vlan = [ "server-vlan" "dmz-vlan" ]; # tagged
networkConfig = {
Bridge = "management"; # untagged
LinkLocalAddressing = "no";
};
};
}As you can see, you don't configure the network directly on the physical interface, you map the network to the interface via vlan or a bridge. If the server needs to be accessable through a network, we also need to give the associated bridge the desired static IPv6. Here the host can be accessed through the management network:
systemd.network.networks = {
"60-management" = with config.schallernetz.networking.subnets.management; {
# NOTE completion of bridge
address = [
"${ip6.prefix}***REMOVED_IPv6***${ip6.suffix}"
"***REMOVED_IPv6***/64"
];
};
}The router has of course slightly more bridge configuration than a normal host. See systems/x86_64-linux/barebonej3160/default.nix for an example.
In the kanidm documentation flollow 5.3 > Default Admin Accounts:
- The URL to the kanidm instance is
https://idm.<yourMainDomain>. - Instead of the docker commands (mentioned in the docs), go into the nixos-container (systemd-nspawn container)
idmand run thekanidmdcommands directly.
In the server:
ssh admin@<host>.<yourMainDomain>
sudo nixos-container root-login idm
kanidmd recover-account admin
kanidmd recover-account idm_adminmodules/nixos/containers/idm/persons.nix:
{
demo_user = {
displayName = "Demo User"; # required
legalName = "Demo User";
mailAddresses = [ "demo.user@example.com" ];
groups = [ "demo_group" ];
};
# ...
}modules/nixos/containers/idm/groups.nix:
{
demo_group.members = [ "demo_user" ];
idm_people_admins.members = [ "demo_user" ];
# ...
}All options: search.nixos.org github:oddlama/kanidm-provision
After rebuilding trigger a credential reset for your users: $ kanidm person credential create-reset-token <USERNAME> [ttl_seconds]
From the client:
nix develop .#idm
kanidm login --name idm_admin
kanidm self whoami --name anonymous
kanidm logout --name idm_adminTake your time. No rush!
-
(NixOS-version upgrade) At a new NixOS release manually update inputs in flake.nix. e.g.
24.11->25.05. -
nix flake update --commit-lock-file -
nix flake checkto check for new eval warnings & errors -
(optional)
nixos-rebuild build --flake .#<host>to check for build errors -
For every host
nixos-rebuild test --flake .#<host>first (especially the router/firewall) and thennixos-rebuild switch --flake .#<host>. Or if errors occurnixos-rebuild boot --flake .#<host>.
The flakes structure is similar to my dotfiles, but without home-manager.
I decided to build a IPv6 only network (for now) because
- global IPv4 addresses are expensive to get nowadays
- it was easier for me to setup (in comparison to NAT in IPv4)
- it makes a clear subnet structure (one subnet always /64)
- from some ISPs you don't get an IPv4 anymore.
I implemented the network with systemd-networkd, because "systemd.network should be preferred over networking.interfaces"
nftables is used as the firewall implementation. It also seperates the subnets you declare with schallernetz.networking.subnets.
Outbound is allowed by default. Inbound is dropped by default, but can be configured with schallernetz.networking.subnets.<name>.firewall.inputRules.
Every service is beeing executed in a seperate NixOS Container.
This has some advanages:
- Every server has its own IP
- Processes are sealed off from the host system (more security)
- Can always be started and stopped, independently from the host
My internal nameserver (modules/nixos/containers/unbound) is serving 'unique local addresses' and the bought public nameserver from the dns provider is serving 'global unique addresses'.
Advantages:
- When internet is down, i can still access my services from within the network.
- Private DNS:
- Improved security and control
- Better performance
- Privacy
Since my ISP changes the prefix of my global unicast address frequently, I had to use DDNS (dynamic DNS), which I implemented with services.inadyn.
