Move hosts to own repos

This commit is contained in:
Christopher Mühl 2026-01-04 23:39:10 +01:00
parent 85dde426dd
commit b1b11cdcd5
No known key found for this signature in database
GPG key ID: 925AC7D69955293F
18 changed files with 0 additions and 746 deletions

View file

@ -1,11 +0,0 @@
# ++ 93_Np: Neptunium
#
# Raspberry Pi / Mini home server environment
{...}: {
elements = {
hostname = "neptunium";
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPjqieS4GkYAa1WRYZpxjgYsj7VGZ9U+rTFCkX8M0umD";
};
};
}

View file

@ -1,52 +0,0 @@
{...}: {
imports = [
./hardware.nix
./traefik.nix
./radicle.nix
./static.nix
./victoria.nix
./solid.nix
./oxigraph.nix
./matrix.nix
];
elements = {
hostname = "alvin";
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBzji6twM8/QdDgFGSUKNmvCm/kEfFMYWZdmgRBbs5Nc";
needs.radiclePrivateKey.rekeyFile = "radicle.age";
needs.radiclePublicKey.rekeyFile = "radicle.pub.age";
needs.victoriametricsPasswordFile.rekeyFile = "victoria-password.age";
};
};
boot.tmp.cleanOnBoot = true;
zramSwap.enable = true;
networking = {
enableIPv6 = true;
firewall = {
enable = true;
allowedTCPPorts = [22 80 443];
};
domain = "contaboserver.net";
defaultGateway = "62.169.24.1";
nameservers = ["8.8.8.8" "8.8.4.4"];
interfaces.ens18 = {
useDHCP = false;
ipv4.addresses = [
{
address = "62.169.31.37";
prefixLength = 21;
}
];
};
};
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO+XpUv6qTqJ7NmYDz9hjvobDBJY9NN3S0TjXD0q2kt2 christopher@cobalt"];
system.stateVersion = "23.11";
}

View file

@ -1,10 +0,0 @@
{modulesPath, ...}: {
imports = [(modulesPath + "/profiles/qemu-guest.nix")];
boot.loader.grub.device = "/dev/sda";
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi"];
boot.initrd.kernelModules = ["nvme"];
fileSystems."/" = {
device = "/dev/sda1";
fsType = "ext4";
};
}

View file

@ -1,36 +0,0 @@
{
inputs,
pkgs,
...
}: {
services = {
matrix-synapse = {
enable = true;
settings = {
server_name = "aleph.garden";
public_baseurl = "https://matrix.aleph.garden";
listeners = [
{
port = 8008;
type = "http";
x_forwarded = true;
tls = false;
resources = [{names = ["client" "federation"];}];
}
];
};
};
# mautrix-whatsapp.enable = true;
# mautrix-telegram.registerToSynapse = {};
# mautrix-signal.registerToSynapse = {};
# mautrix-discord.enable = true;
traefik.routes.matrix = {
rule = "Host(`matrix.aleph.garden`)";
url = "http://localhost:8008";
};
};
}

View file

@ -1,38 +0,0 @@
{pkgs, ...}: {
# Create dedicated user and group
users.users.oxigraph = {
isSystemUser = true;
group = "oxigraph";
description = "Oxigraph SPARQL database service user";
};
users.groups.oxigraph = {};
# Configure systemd service
systemd.services.oxigraph = {
description = "Oxigraph SPARQL database server";
after = ["network.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
ExecStart = "${pkgs._elements.oxigraph}/bin/oxigraph serve --location /var/lib/oxigraph --bind 127.0.0.1:7878";
Restart = "on-failure";
User = "oxigraph";
Group = "oxigraph";
StateDirectory = "oxigraph";
# Security hardening
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = "/var/lib/oxigraph";
};
};
# Configure Traefik route for public access
services.traefik.routes.sparql = {
rule = "Host(`sparql.toph.so`)";
url = "http://localhost:7878";
};
}

View file

@ -1,68 +0,0 @@
{config, ...}: let
nodeAddress = "seed.toph.so";
radConfig = config.services.radicle;
followed = [
"z6Mkm1WGVW5Zr6Ubn2aJU7S26Knjum3Y3iSC39zJ8EojRkt9" # toph
];
seedRepositories = [
"rad:zBNXLtTqUu9LBZHCPFShAeXnp5Gz" # radicle-ci
"rad:z254T5p17bdFPmzfDojsdjo4HjpoZ" # radicle-infra
];
in {
services = {
radicle = {
enable = true;
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEihs1RjZ52Vcy+NJuFhiRbEp5SfwND3b3oSjD2V0HTG";
privateKeyFile = config.age.secrets.radiclePrivateKey.path;
httpd = {
enable = true;
nginx.serverName = nodeAddress;
};
# Seeding node
node = {
listenAddress = "[::0]";
openFirewall = true;
};
settings = {
preferredSeeds = [
];
node = {
alias = nodeAddress;
# externalAddresses = ["${nodeAddress}:${builtins.toString radConfig.node.listenPort}"];
follow = followed;
seeds = seedRepositories;
seedingPolicy = {
default = "allow";
scope = "all";
};
};
web = {
description = ''
Hi there! I'm toph, a passionate federated and semantic web developer.
This is my main Radicle seed node that I also use to showcase my projects.
I'll try to seed every repo that I actively use for my code that's also
hosted on Radicle.
Be sure to also check out my GitHub at https://github.com/tophcodes.
'';
pinned.repositories = [
"rad:z4VmSKKMbAqbwqsMXWvyvrxTSAZFS"
];
};
};
};
traefik.routes.radicle-seed = {
rule = "Host(`${nodeAddress}`)";
url = "http://localhost:${builtins.toString radConfig.httpd.listenPort}";
};
};
}

View file

@ -1,83 +0,0 @@
{
inputs,
pkgs,
...
}: {
imports = [
inputs.community-solid-server.nixosModules.default
];
services = {
solid-server = {
enable = true;
rootFilePath = "/var/lib/solid";
baseUrl = "https://pod.toph.so";
configFile = pkgs.writeTextFile {
name = "solid.config.json";
text = ''
{
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
"import": [
"css:config/app/init/initialize-root-pod.json",
"css:config/app/main/default.json",
"css:config/app/variables/default.json",
"css:config/http/handler/default.json",
"css:config/http/middleware/default.json",
"css:config/http/notifications/all.json",
"css:config/http/server-factory/http.json",
"css:config/http/static/default.json",
"css:config/identity/access/public.json",
"css:config/identity/email/default.json",
"css:config/identity/handler/no-accounts-pods.json",
"css:config/identity/oidc/default.json",
"css:config/identity/ownership/token.json",
"css:config/identity/pod/static.json",
"css:config/ldp/authentication/dpop-bearer.json",
"css:config/ldp/authorization/webacl.json",
"css:config/ldp/handler/default.json",
"css:config/ldp/metadata-parser/default.json",
"css:config/ldp/metadata-writer/default.json",
"css:config/ldp/modes/default.json",
"css:config/storage/backend/file.json",
"css:config/storage/key-value/resource-store.json",
"css:config/storage/location/root.json",
"css:config/storage/middleware/default.json",
"css:config/util/auxiliary/acl.json",
"css:config/util/identifiers/suffix.json",
"css:config/util/index/default.json",
"css:config/util/logging/winston.json",
"css:config/util/representation-conversion/default.json",
"css:config/util/resource-locker/file.json",
"css:config/util/variables/default.json"
],
"@graph": [
{
"comment": [
"A Solid server that stores its resources on disk and uses WAC for authorization.",
"A pod will be created in the root with the email/password login defined here.",
"It is advised to immediately change this password after starting the server."
]
},
{
"@id": "urn:solid-server:default:RootPodInitializer",
"@type": "AccountInitializer",
"email": "toki@toph.so",
"password": "ssecretohno!"
}
]
}
'';
};
};
traefik.routes.solid-pod = {
rule = "Host(`pod.toph.so`)";
url = "http://localhost:3000";
};
};
systemd.tmpfiles.rules = [
"d /var/lib/solid - - - - -"
];
}

View file

@ -1,21 +0,0 @@
{...}: let
root = "/var/lib/sws";
in {
imports = [
./static/tophso.nix
./static/radicle-explorer.nix
];
services = {
static-web-server = {
enable = true;
listen = "[::]:89";
inherit root;
configuration = {};
};
};
systemd.tmpfiles.rules = [
"d ${root} - - - - -"
];
}

View file

@ -1,35 +0,0 @@
{pkgs, ...}: let
name = "radicle.toph.so";
explorer = pkgs.radicle-explorer.withConfig {
preferredSeeds = [
{
hostname = "seed.toph.so";
port = 443;
scheme = "https";
}
];
};
in {
services = {
static-web-server.configuration.advanced = {
rewrites = [
{
source = "{**}";
destination = "https://${name}/";
}
];
virtual-hosts = [
{
host = name;
root = explorer;
}
];
};
traefik.routes.radicle = {
rule = "Host(`${name}`)";
url = "http://localhost:89";
};
};
}

View file

@ -1,34 +0,0 @@
{pkgs, ...}: let
name = "toph.so";
tophso = pkgs.writeTextFile {
inherit name;
destination = "/index.html";
text = ''
<!DOCTYPE html>
<html>
<head>
<title>toph.so</title>
<meta charset="utf-8"/>
</head>
<body>
<a rel="me" href="https://mas.to/@padarom">Mastodon</a>
</body>
</html>
'';
};
in {
services = {
static-web-server.configuration.advanced.virtual-hosts = [
{
host = name;
root = tophso;
}
];
traefik.routes.toph = {
rule = "Host(`${name}`)";
url = "http://localhost:89";
};
};
}

View file

@ -1,32 +0,0 @@
{
config,
lib,
...
}: {
services.traefik = {
enable = true;
postmasterEmail = "hosting@muehl.dev";
# routes = {
# staticsite = {
# rule = "Host(`toph.so`)";
# url = "http://localhost:8080";
# };
# solid-pod = {
# rule = "Host(`solid.toph.so`)";
# url = "http://localhost:8096";
# };
# radicle = {
# rule = "Host(`radicle.toph.so`)";
# url = "http://localhost:8097";
# };
# forgejo = {
# rule = "Host(`git.toph.so`)";
# url = "http://localhost:3000";
# };
# };
};
}

View file

@ -1,16 +0,0 @@
{config, ...}: {
services = {
victoriametrics = {
enable = true;
retentionPeriod = "5y";
basicAuthUsername = "victoria-with-the-secrets";
basicAuthPasswordFile = config.age.secrets.victoriametricsPasswordFile.path;
};
traefik.routes.victoriametrics = {
rule = "Host(`vm.toph.so`)";
url = "http://localhost:8428";
};
};
}

View file

@ -1,56 +0,0 @@
# ++ 4_Be: Beryllium
#
# NUC / HomeLab environment
{pkgs, ...}: {
imports = [
./hardware.nix
./disks.nix
];
elements = {
hostname = "beryllium";
users = ["christopher"];
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBUKDCjB0VpQubi8BfnYKbh4MIE1tcvKQesdoPE4NXAf";
};
};
networking.firewall.enable = false;
networking.dhcpcd.IPv6rs = false;
users.users.christopher.linger = true; # autostart of quadlets before login
users.users.christopher.autoSubUidGidRange = true;
users.users.christopher.openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVKJfY6B9TsUPdPXy3tkqL42sJgJRz3NOOKTqhytMMf christopher@cobalt"];
users.users.root.openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVKJfY6B9TsUPdPXy3tkqL42sJgJRz3NOOKTqhytMMf christopher@cobalt"];
services = {
openssh = {
enable = true;
ports = [7319];
settings.PasswordAuthentication = false;
};
beszel-agent = {
enable = true;
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMkUPOw28Cu2LMuzfmvjT/L2ToNHcADwGyGvSpJ4wH2T";
};
apcupsd = {
enable = true;
configText = ''
UPSTYPE usb
NISIP 0.0.0.0
BATTERYLEVEL 50
MINUTES 5
'';
};
};
# Enable privileged ports for rootless pods
boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = "53";
environment.systemPackages = with pkgs; [
helix
podman-compose
];
}

View file

@ -1,63 +0,0 @@
let
mkDrive = bootMountpoint: {
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for grub MBR
};
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = bootMountpoint;
mountOptions = ["umask=0077"];
};
};
swap = {
size = "8G";
content = {
type = "swap";
discardPolicy = "both";
};
};
mdadm = {
size = "100%";
content = {
type = "mdraid";
name = "raid1";
};
};
};
};
};
in {
disko.devices = {
disk = {
one = mkDrive "/boot";
two = mkDrive "/boot2";
};
mdadm = {
raid1 = {
type = "mdadm";
level = 1;
content = {
type = "gpt";
partitions.primary = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
}

View file

@ -1,61 +0,0 @@
{
config,
pkgs,
...
}: {
imports = [
./disko.nix
];
elements.secrets.needs.smbSecrets = "smb-secrets.age";
# Set up two main drives for RAID 1
disko.devices.disk = {
one.device = "/dev/sda";
two.device = "/dev/sdb";
};
# Install GRUB to both drives (/boot and /boot2) so that we'll be able to boot
# even if one of them fails
boot = {
loader = {
efi.canTouchEfiVariables = true;
grub = {
enable = true;
efiSupport = true;
device = "nodev";
mirroredBoots = [
{
devices = ["/dev/sda"];
path = "/boot";
}
{
devices = ["/dev/sdb"];
path = "/boot2";
}
];
};
};
# Set up mdmon to notify me when one of the drives fails
swraid.mdadmConf = ''
MAILADDR raid@muehl.dev
'';
};
# Mount the NAS locally via CIFS (Windows share)
fileSystems = builtins.listToAttrs (
map (v: {
name = "/mnt/nuc/${v}";
value = {
device = "//10.1.0.1/${v}";
fsType = "cifs";
options = let
automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
in ["${automount_opts},credentials=${config.age.secrets.smbSecrets.path},uid=1000,gid=100,vers=1.0"];
};
}) ["_NAS_Media" "Ix"]
);
environment.systemPackages = [pkgs.cifs-utils];
}

View file

@ -1,27 +0,0 @@
{
config,
lib,
...
}: {
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "rtsx_pci_sdmmc"];
boot.initrd.kernelModules = [];
boot.kernelModules = ["kvm-intel"];
boot.extraModulePackages = [];
boot.swraid.enable = true;
networking.useDHCP = lib.mkDefault true;
virtualisation.virtualbox.guest.enable = true;
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
fileSystems."/mnt/external" = {
device = "/dev/disk/by-uuid/0fc53086-d326-4663-973c-aa224a3f8589";
fsType = "ext4";
options = [
"nofail"
"exec"
"users"
];
};
}

View file

@ -1,93 +0,0 @@
# ++ 63_Eu: Europium
#
# Hosted VPS used primarily as an email server
{pkgs, ...}: {
imports = [./hardware.nix];
system.stateVersion = "23.11";
elements = {
hostname = "europium";
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAzw6hzrX3zDJAiMfhVpU+t1xr9C2PxJ9rf4HUfRzTiU";
needs = {
compose = {
rekeyFile = "stalwart-compose.yaml.age";
path = "/opt/stalwart/compose.yaml";
symlink = false;
mode = "0644";
};
stalwart = {
rekeyFile = "stalwart-config.toml.age";
path = "/opt/stalwart/stalwart/etc/config.toml";
symlink = false;
mode = "0644";
};
traefik = {
rekeyFile = "stalwart-traefik.yml.age";
path = "/opt/stalwart/loadbalancer/traefik.yml";
symlink = false;
mode = "0644";
};
};
};
};
boot.tmp.cleanOnBoot = true;
zramSwap.enable = true;
# Used to generate a FQDN in the internal contabo network
networking = {
domain = "contaboserver.net";
firewall = {
enable = true;
allowedTCPPorts = [
# ssh
22
# http + https
80
443
# stalwart ports
143
993
587
465
110
995
4190
# portainer agent
9001
];
};
};
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOJO3cs5ldXTibguhJQKwopdssnfGwwIHS5vyOQTvzbm christopher@cobalt"];
virtualisation.docker.enable = true;
environment.systemPackages = with pkgs; [
docker-compose
vim
];
system.activationScripts = {
dockerNetwork = {
text = ''
# Don't fail in case the network can't be created (in case it already exists)
${pkgs.docker}/bin/docker network create traefik-proxy || true
'';
};
};
users.users.stalwart = {
home = "/opt/stalwart";
isSystemUser = true;
group = "stalwart";
extraGroups = ["docker"];
};
users.groups.stalwart = {};
}

View file

@ -1,10 +0,0 @@
{modulesPath, ...}: {
imports = [(modulesPath + "/profiles/qemu-guest.nix")];
boot.loader.grub.device = "/dev/sda";
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi"];
boot.initrd.kernelModules = ["nvme"];
fileSystems."/" = {
device = "/dev/sda3";
fsType = "ext4";
};
}