feat: harbor
This commit is contained in:
@@ -44,6 +44,7 @@
|
|||||||
inputs.home-manager.flakeModules.home-manager
|
inputs.home-manager.flakeModules.home-manager
|
||||||
./hosts/comfy-station
|
./hosts/comfy-station
|
||||||
./hosts/monolith
|
./hosts/monolith
|
||||||
|
./hosts/harbor
|
||||||
(./home + "/jonas@comfy-station")
|
(./home + "/jonas@comfy-station")
|
||||||
(./home + "/jonas@monolith")
|
(./home + "/jonas@monolith")
|
||||||
(import-tree ./modules)
|
(import-tree ./modules)
|
||||||
|
|||||||
150
hosts/harbor/configuration.nix
Normal file
150
hosts/harbor/configuration.nix
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
imports = [
|
||||||
|
./hardware-configuration.nix
|
||||||
|
./disko.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# Secret management
|
||||||
|
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
|
||||||
|
sops.secrets."nextcloud-admin-pass" = {
|
||||||
|
sopsFile = ../../secrets/harbor/nextcloud.yaml;
|
||||||
|
owner = "nextcloud";
|
||||||
|
key = "admin-pass";
|
||||||
|
};
|
||||||
|
sops.secrets."wg-priv" = {
|
||||||
|
sopsFile = ../../secrets/harbor/wg.yaml;
|
||||||
|
key = "privateKey";
|
||||||
|
};
|
||||||
|
sops.secrets."gitea-db-pass" = {
|
||||||
|
sopsFile = ../../secrets/harbor/gitea.yaml;
|
||||||
|
owner = config.services.gitea.user;
|
||||||
|
key = "databasePassword";
|
||||||
|
};
|
||||||
|
sops.secrets."gotify-admin-pass" = {
|
||||||
|
sopsFile = ../../secrets/harbor/gotify.yaml;
|
||||||
|
owner = config.hive.gotify-instance.user;
|
||||||
|
key = "adminPassword";
|
||||||
|
};
|
||||||
|
|
||||||
|
# gc settings and binary caches
|
||||||
|
nix = {
|
||||||
|
settings = {
|
||||||
|
substituters = [
|
||||||
|
"https://aseipp-nix-cache.freetls.fastly.net"
|
||||||
|
"https://nix-community.cachix.org"
|
||||||
|
"https://cache.nixos.org/"
|
||||||
|
];
|
||||||
|
experimental-features = ["nix-command" "flakes"];
|
||||||
|
auto-optimise-store = true;
|
||||||
|
};
|
||||||
|
gc = {
|
||||||
|
automatic = true;
|
||||||
|
dates = "weekly";
|
||||||
|
options = "--delete-older-than 30d";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# user with ssh access
|
||||||
|
users.users.jonas = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Jonas";
|
||||||
|
extraGroups = ["wheel"];
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCyCyYsMSiy7shcehlzJEbCyRiHk+cicFB35Bc2uc4PjjkCjswLh01fRAV2QcplrNkH/5F4GBTbOoZHHc7/AVLyUxgwDC9ffD2i7fevuGpfBFy9D30uz6jDekxXkmRmIlidXLdG1Fh4zwVejGlwdhUu/Zb7PonO/dktx3EFdf1SpnW+y75anN85zoGsld7KQk42wEd0zXtCgx4CKI6Vvt6heWCEiJ9wyw1sLpTJr4H8In236CUj1/r1qY9Gfa8n9NA0J9XCpcwSCEWGRKQNicoQIpnp5txrgzaUq4r6qBKHmImYXmSTVnDZ9dJLRYNu2lDvBtTXP4ztlR6Lpxs873fPg51qgaX9rRVMMo/gGjq8fOFWsDVaJZab9VY3hZYNCKIbWFqo4GKyCQs9Xfzr2AUACm09HWiYMTefwEypOzvUb4z+LF2B/0c5XmghLF/TOzLVgDXzAgWMH4mCnPh9EDLHTtoJaGNURler9VRV8yQyLH6oK9UpHZovCFs7HpFN+WPv2QVFfkK8aHg7tnklFsT78z154bjuspiEI/fFGmTxoQUGufmHlRy/9GQDusgNfe24ZEB2hHBVjKv29XdIfvFAhoPVpA6+O/N3feSlmVISaU+8QraVQEf/TuQjopDUWpJTmqSxKvQSTPwcyWDy6NtcJ85bGAu6jSUGC3ouH4Rb2Q== cardno:000609618602"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
users.defaultUserShell = pkgs.zsh;
|
||||||
|
programs.zsh.enable = true;
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
settings.PasswordAuthentication = false;
|
||||||
|
settings.KbdInteractiveAuthentication = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# hive modules
|
||||||
|
hive.gitea-instance.enable = true;
|
||||||
|
hive.gitea-instance.nativeRunner = true;
|
||||||
|
hive.gitea-instance.instanceFQDN = "git.jroeger.de";
|
||||||
|
hive.gitea-instance.databasePasswordFile = config.sops.secrets.gitea-db-pass.path;
|
||||||
|
hive.gotify-instance.enable = true;
|
||||||
|
hive.gotify-instance.instanceFQDN = "gotify.jroeger.de";
|
||||||
|
hive.gotify-instance.adminPasswordSopsKey = config.sops.secrets.gotify-admin-pass.name;
|
||||||
|
hive.nextcloud-instance.enable = true;
|
||||||
|
hive.nextcloud-instance.ssl = true;
|
||||||
|
hive.nextcloud-instance.adminPasswordFile = config.sops.secrets.nextcloud-admin-pass.path;
|
||||||
|
hive.nextcloud-instance.instanceFQDN = "nextcloud.jroeger.de";
|
||||||
|
hive.minecraft-server.enable = true;
|
||||||
|
hive.borg-server.enable = true;
|
||||||
|
hive.borg-server.repositories.comfy-station.ssh_public_key = builtins.readFile (../../static/keys + "/borg-jonas@comfy-station.pub");
|
||||||
|
hive.wg.server.enable = true;
|
||||||
|
hive.wg.server.privateKeyFile = config.sops.secrets.wg-priv.path;
|
||||||
|
|
||||||
|
# This value determines the NixOS release from which the default
|
||||||
|
# settings for stateful data, like file locations and database versions
|
||||||
|
# on your system were taken. It‘s perfectly fine and recommended to leave
|
||||||
|
# this value at the release version of the first install of this system.
|
||||||
|
# Before changing this value read the documentation for this option
|
||||||
|
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||||
|
system.stateVersion = "25.11"; # Did you read the comment?
|
||||||
|
|
||||||
|
# VPS compat
|
||||||
|
boot.loader.grub.enable = true;
|
||||||
|
boot.loader.grub.device = "/dev/sda";
|
||||||
|
boot.loader.grub.version = 2;
|
||||||
|
boot.kernelParams = [
|
||||||
|
"net.ifnames=0" # ensure iface is called eth0
|
||||||
|
"ip=173.249.42.252::173.249.42.1:255.255.255.0:harbor:eth0:none:8.8.8.8"
|
||||||
|
];
|
||||||
|
networking.networkmanager.enable = true;
|
||||||
|
networking = {
|
||||||
|
# Static network configuration
|
||||||
|
hostName = "harbor";
|
||||||
|
domain = "jroeger.de";
|
||||||
|
defaultGateway = "173.249.42.1";
|
||||||
|
nameservers = ["8.8.8.8"];
|
||||||
|
interfaces.eth0.ipv4.addresses = [
|
||||||
|
{
|
||||||
|
address = "173.249.42.252";
|
||||||
|
prefixLength = 24;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
# Temporary ssh server for disk unlock
|
||||||
|
boot.initrd = {
|
||||||
|
availableKernelModules = ["virtio_pci"];
|
||||||
|
network = {
|
||||||
|
enable = true;
|
||||||
|
ssh = {
|
||||||
|
enable = true;
|
||||||
|
port = 2222;
|
||||||
|
authorizedKeys = [
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCyCyYsMSiy7shcehlzJEbCyRiHk+cicFB35Bc2uc4PjjkCjswLh01fRAV2QcplrNkH/5F4GBTbOoZHHc7/AVLyUxgwDC9ffD2i7fevuGpfBFy9D30uz6jDekxXkmRmIlidXLdG1Fh4zwVejGlwdhUu/Zb7PonO/dktx3EFdf1SpnW+y75anN85zoGsld7KQk42wEd0zXtCgx4CKI6Vvt6heWCEiJ9wyw1sLpTJr4H8In236CUj1/r1qY9Gfa8n9NA0J9XCpcwSCEWGRKQNicoQIpnp5txrgzaUq4r6qBKHmImYXmSTVnDZ9dJLRYNu2lDvBtTXP4ztlR6Lpxs873fPg51qgaX9rRVMMo/gGjq8fOFWsDVaJZab9VY3hZYNCKIbWFqo4GKyCQs9Xfzr2AUACm09HWiYMTefwEypOzvUb4z+LF2B/0c5XmghLF/TOzLVgDXzAgWMH4mCnPh9EDLHTtoJaGNURler9VRV8yQyLH6oK9UpHZovCFs7HpFN+WPv2QVFfkK8aHg7tnklFsT78z154bjuspiEI/fFGmTxoQUGufmHlRy/9GQDusgNfe24ZEB2hHBVjKv29XdIfvFAhoPVpA6+O/N3feSlmVISaU+8QraVQEf/TuQjopDUWpJTmqSxKvQSTPwcyWDy6NtcJ85bGAu6jSUGC3ouH4Rb2Q== cardno:000609618602"
|
||||||
|
];
|
||||||
|
hostKeys = ["/etc/secrets/initrd/ssh_host_rsa_key"];
|
||||||
|
shell = "/bin/cryptsetup-askpass";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Set your time zone.
|
||||||
|
time.timeZone = "Europe/Berlin";
|
||||||
|
|
||||||
|
# Select internationalisation properties.
|
||||||
|
i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
i18n.extraLocaleSettings = {
|
||||||
|
LC_ADDRESS = "de_DE.UTF-8";
|
||||||
|
LC_IDENTIFICATION = "de_DE.UTF-8";
|
||||||
|
LC_MEASUREMENT = "de_DE.UTF-8";
|
||||||
|
LC_MONETARY = "de_DE.UTF-8";
|
||||||
|
LC_NAME = "de_DE.UTF-8";
|
||||||
|
LC_NUMERIC = "de_DE.UTF-8";
|
||||||
|
LC_PAPER = "de_DE.UTF-8";
|
||||||
|
LC_TELEPHONE = "de_DE.UTF-8";
|
||||||
|
LC_TIME = "de_DE.UTF-8";
|
||||||
|
};
|
||||||
|
console.keyMap = "de";
|
||||||
|
}
|
||||||
25
hosts/harbor/default.nix
Normal file
25
hosts/harbor/default.nix
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
inputs,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
flake.nixosConfigurations.harbor = inputs.nixpkgs.lib.nixosSystem {
|
||||||
|
modules = [
|
||||||
|
({...}: {
|
||||||
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
})
|
||||||
|
|
||||||
|
./configuration.nix
|
||||||
|
|
||||||
|
inputs.sops-nix.nixosModules.sops
|
||||||
|
inputs.disko.nixosModules.disko
|
||||||
|
self.nixosModules.nix-scripts
|
||||||
|
self.nixosModules.gitea-instance
|
||||||
|
self.nixosModules.gotify-instance
|
||||||
|
self.nixosModules.nextcloud-instance
|
||||||
|
self.nixosModules.minecraft-server
|
||||||
|
self.nixosModules.borg-server
|
||||||
|
self.nixosModules.wireguard-server
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
71
hosts/harbor/disko.nix
Normal file
71
hosts/harbor/disko.nix
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
let
|
||||||
|
btrfsopt = [
|
||||||
|
"compress=zstd"
|
||||||
|
"noatime"
|
||||||
|
"ssd"
|
||||||
|
"space_cache=v2"
|
||||||
|
"user_subvol_rm_allowed"
|
||||||
|
];
|
||||||
|
in {
|
||||||
|
disko.devices = {
|
||||||
|
disk = {
|
||||||
|
main = {
|
||||||
|
type = "disk";
|
||||||
|
device = "/dev/sda";
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
boot = {
|
||||||
|
name = "boot";
|
||||||
|
size = "1M";
|
||||||
|
type = "ef02";
|
||||||
|
};
|
||||||
|
esp = {
|
||||||
|
name = "esp";
|
||||||
|
size = "500M";
|
||||||
|
type = "ef00";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "vfat";
|
||||||
|
mountpoint = "/boot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
luks = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "luks";
|
||||||
|
name = "nixos";
|
||||||
|
passwordFile = "/tmp/pass";
|
||||||
|
additionalKeyFiles = ["/nixos-enc.key"];
|
||||||
|
extraFormatArgs = [
|
||||||
|
"--type luks1"
|
||||||
|
"--iter-time 3000"
|
||||||
|
];
|
||||||
|
settings = {
|
||||||
|
allowDiscards = true;
|
||||||
|
};
|
||||||
|
content = {
|
||||||
|
type = "btrfs";
|
||||||
|
subvolumes = {
|
||||||
|
"@root" = {
|
||||||
|
mountpoint = "/";
|
||||||
|
mountOptions = btrfsopt;
|
||||||
|
};
|
||||||
|
"@home" = {
|
||||||
|
mountpoint = "/home";
|
||||||
|
mountOptions = btrfsopt;
|
||||||
|
};
|
||||||
|
"@nix" = {
|
||||||
|
mountpoint = "/nix";
|
||||||
|
mountOptions = btrfsopt;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
21
hosts/harbor/hardware-configuration.nix
Normal file
21
hosts/harbor/hardware-configuration.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
|
# and may be overwritten by future invocations. Please make changes
|
||||||
|
# to /etc/nixos/configuration.nix instead.
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod"];
|
||||||
|
boot.initrd.kernelModules = [];
|
||||||
|
boot.kernelModules = [];
|
||||||
|
boot.extraModulePackages = [];
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
peers = import ./peers.nix {inherit lib;};
|
peers = import ./peers.nix {inherit lib;};
|
||||||
in {
|
in {
|
||||||
options.hive.wg.server = {
|
options.hive.wg.server = {
|
||||||
|
enable = lib.mkEnableOption "Enable WireGuard server";
|
||||||
port = lib.mkOption {
|
port = lib.mkOption {
|
||||||
type = lib.types.port;
|
type = lib.types.port;
|
||||||
default = 51820;
|
default = 51820;
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = lib.mkIf cfg.enable {
|
||||||
# Firewall rule
|
# Firewall rule
|
||||||
networking.firewall.allowedUDPPorts = [cfg.port];
|
networking.firewall.allowedUDPPorts = [cfg.port];
|
||||||
|
|
||||||
|
|||||||
63
modules/services/borg-server.nix
Normal file
63
modules/services/borg-server.nix
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
flake.nixosModules.borg-server = {
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.hive.borg-server;
|
||||||
|
in {
|
||||||
|
options.hive.borg-server = {
|
||||||
|
enable = lib.mkEnableOption "Enable the borg server";
|
||||||
|
package = lib.mkOption {
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.borgbackup;
|
||||||
|
example = "pkgs.borgbackup";
|
||||||
|
description = "The borg package to use";
|
||||||
|
};
|
||||||
|
borg_user = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "borg";
|
||||||
|
default = "borg";
|
||||||
|
description = "The user for the borg repository home.";
|
||||||
|
};
|
||||||
|
repositories_path = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
example = "/var/lib/borg-repositories";
|
||||||
|
default = "/var/lib/borg-repositories";
|
||||||
|
description = "The user for the borg repository home.";
|
||||||
|
};
|
||||||
|
repositories = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.strMatching "^[a-zA-Z0-9._-]+$");
|
||||||
|
default = null;
|
||||||
|
example = "borg-repo";
|
||||||
|
description = "The name of the borg repository. If null, use key of attrset";
|
||||||
|
};
|
||||||
|
ssh_public_key = lib.mkOption {
|
||||||
|
type = lib.types.singleLineStr;
|
||||||
|
example = "ssh-rsa AAAA...";
|
||||||
|
description = "The path to the public key for the borg repository.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
users.users.${cfg.borg_user} = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Borg user";
|
||||||
|
home = cfg.repositories_path;
|
||||||
|
createHome = true;
|
||||||
|
extraGroups = ["borg"];
|
||||||
|
openssh.authorizedKeys.keys =
|
||||||
|
lib.attrsets.mapAttrsToList
|
||||||
|
(key: repo: "command=\"${cfg.package}/bin/borg serve --restrict-to-path=${cfg.repositories_path}/${lib.defaultTo key repo.name}\",restrict ${repo.ssh_public_key}")
|
||||||
|
cfg.repositories;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
125
modules/services/gitea-instance.nix
Normal file
125
modules/services/gitea-instance.nix
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
{
|
||||||
|
flake.nixosModules.gitea-instance = {
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.hive.gitea-instance;
|
||||||
|
in {
|
||||||
|
options.hive.gitea-instance = {
|
||||||
|
enable = lib.mkEnableOption "Enable the Gitea instance";
|
||||||
|
|
||||||
|
instanceFQDN = lib.mkOption {
|
||||||
|
type = lib.types.singleLineStr;
|
||||||
|
example = "git.example.com";
|
||||||
|
description = "Fully qualified domain name of the Gitea instance";
|
||||||
|
};
|
||||||
|
|
||||||
|
databasePasswordFile = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
example = "/etc/gitea-db-pass.txt";
|
||||||
|
description = "Path to the file containing the Gitea database password";
|
||||||
|
};
|
||||||
|
nativeRunner = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Install a gitea act_runner using the native nix store";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
# Gitea instance
|
||||||
|
services.gitea = {
|
||||||
|
enable = true;
|
||||||
|
lfs.enable = true;
|
||||||
|
appName = "Git yourself some Tea!";
|
||||||
|
database = {
|
||||||
|
name = "gitea";
|
||||||
|
type = "postgres";
|
||||||
|
passwordFile = cfg.databasePasswordFile;
|
||||||
|
};
|
||||||
|
settings = {
|
||||||
|
server.PROTOCOL = "http+unix";
|
||||||
|
server.ROOT_URL = "https://${cfg.instanceFQDN}/";
|
||||||
|
server.DOMAIN = cfg.instanceFQDN;
|
||||||
|
service.DISABLE_REGISTRATION = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Fallback server with only 403
|
||||||
|
services.nginx.virtualHosts.${config.networking.domain} = lib.mkDefault {
|
||||||
|
default = true;
|
||||||
|
locations."/".return = 403;
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Virtual host for gitea
|
||||||
|
services.nginx.virtualHosts."${cfg.instanceFQDN}" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://unix:/run/gitea/gitea.sock";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Database setup
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [config.services.gitea.user];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = config.services.gitea.database.user;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# act_runner
|
||||||
|
services.gitea-actions-runner = lib.mkIf cfg.nativeRunner {
|
||||||
|
instances.nixos-host = {
|
||||||
|
enable = true;
|
||||||
|
name = "nixos-host-runner";
|
||||||
|
url = "https://${cfg.instanceFQDN}";
|
||||||
|
tokenFile = "/var/lib/gitea-registration/nixos-host";
|
||||||
|
|
||||||
|
labels = ["nixos:host"];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
runner = {
|
||||||
|
capacity = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
systemd.services.gitea-runner-nixos-host = lib.mkIf cfg.nativeRunner {
|
||||||
|
after = ["gitea-runner-gen-token.service"];
|
||||||
|
requires = ["gitea-runner-gen-token.service"];
|
||||||
|
serviceConfig.Environment = ''
|
||||||
|
PATH=/run/current-system/sw/bin:/usr/bin:/bin
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
systemd.services.gitea-runner-gen-token = lib.mkIf cfg.nativeRunner {
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
after = ["gitea.service"];
|
||||||
|
environment = {
|
||||||
|
GITEA_CUSTOM = "/var/lib/gitea/custom";
|
||||||
|
GITEA_WORK_DIR = "/var/lib/gitea";
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
set -euo pipefail
|
||||||
|
token=$(${config.services.gitea.package}/bin/gitea actions generate-runner-token)
|
||||||
|
echo "TOKEN=$token" > /var/lib/gitea-registration/nixos-host
|
||||||
|
'';
|
||||||
|
unitConfig.ConditionPathExists = ["!/var/lib/gitea-registration/nixos-host"];
|
||||||
|
serviceConfig = {
|
||||||
|
User = "gitea";
|
||||||
|
Group = "gitea";
|
||||||
|
StateDirectory = "gitea-registration";
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
133
modules/services/gotify-instance.nix
Normal file
133
modules/services/gotify-instance.nix
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
flake.nixosModules.gotify-instance = {
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.hive.gotify-instance;
|
||||||
|
server-config = {
|
||||||
|
server = {
|
||||||
|
listenaddr = "localhost";
|
||||||
|
port = 54545;
|
||||||
|
ssl.enabled = false;
|
||||||
|
ssl.redirecttohttps = false;
|
||||||
|
cors.alloworigins = ["${cfg.instanceFQDN}"];
|
||||||
|
stream.allowedorigins = ["${cfg.instanceFQDN}"];
|
||||||
|
};
|
||||||
|
database = {
|
||||||
|
dialect = "postgres";
|
||||||
|
connection = "host=/run/postgresql dbname=${cfg.user} user=${cfg.user}";
|
||||||
|
};
|
||||||
|
defaultuser = {
|
||||||
|
name = "admin";
|
||||||
|
pass = config.sops.placeholder.${cfg.adminPasswordSopsKey};
|
||||||
|
};
|
||||||
|
registration = false;
|
||||||
|
};
|
||||||
|
server-config-yaml = lib.generators.toYAML {} server-config;
|
||||||
|
in {
|
||||||
|
options.hive.gotify-instance = {
|
||||||
|
enable = lib.mkEnableOption "Enable the Gotify instance";
|
||||||
|
instanceFQDN = lib.mkOption {
|
||||||
|
type = lib.types.singleLineStr;
|
||||||
|
example = "gotify.example.com";
|
||||||
|
description = "Fully qualified domain name of the Gotify instance";
|
||||||
|
};
|
||||||
|
user = lib.mkOption {
|
||||||
|
type = lib.types.singleLineStr;
|
||||||
|
default = "gotify";
|
||||||
|
description = "The user to run the service as";
|
||||||
|
};
|
||||||
|
group = lib.mkOption {
|
||||||
|
type = lib.types.singleLineStr;
|
||||||
|
default = "gotify";
|
||||||
|
description = "The group to run the service as";
|
||||||
|
};
|
||||||
|
adminPasswordSopsKey = lib.mkOption {
|
||||||
|
type = lib.types.singleLineStr;
|
||||||
|
description = "The SOPS key for the default admin user";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.gotify.enable = true;
|
||||||
|
|
||||||
|
# Config setup
|
||||||
|
sops.templates."gotify-server-config.yml" = {
|
||||||
|
owner = cfg.user;
|
||||||
|
content = server-config-yaml;
|
||||||
|
};
|
||||||
|
environment.etc."gotify/config.yml".source = config.sops.templates."gotify-server-config.yml".path;
|
||||||
|
|
||||||
|
# User setup
|
||||||
|
users.users = lib.mkIf (cfg.user == "gotify") {
|
||||||
|
gotify = {
|
||||||
|
description = "Gotify service";
|
||||||
|
useDefaultShell = true;
|
||||||
|
group = cfg.group;
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups = lib.mkIf (cfg.group == "gotify") {
|
||||||
|
gotify = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure gotify to run as the specified user (for postgres authentication)
|
||||||
|
systemd.services.gotify-server = {
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = lib.mkForce false;
|
||||||
|
User = cfg.user;
|
||||||
|
RuntimeDirectory = "gotify";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Fallback server with only 403
|
||||||
|
services.nginx.virtualHosts.${config.networking.domain} = lib.mkDefault {
|
||||||
|
default = true;
|
||||||
|
locations."/".return = 403;
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Virtual host for gotify
|
||||||
|
services.nginx.virtualHosts."${cfg.instanceFQDN}" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${server-config.server.listenaddr}:${toString server-config.server.port}";
|
||||||
|
extraConfig = ''
|
||||||
|
# Ensuring it can use websockets
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto http;
|
||||||
|
proxy_redirect http:// $scheme://;
|
||||||
|
|
||||||
|
# The proxy must preserve the host because gotify verifies the host with the origin
|
||||||
|
# for WebSocket connections
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
|
||||||
|
# These sets the timeout so that the websocket can stay alive
|
||||||
|
proxy_connect_timeout 1m;
|
||||||
|
proxy_send_timeout 1m;
|
||||||
|
proxy_read_timeout 1m;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Database setup
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [cfg.user];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = cfg.user;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
36
modules/services/minecraft-server/_loadCurseForge.nix
Normal file
36
modules/services/minecraft-server/_loadCurseForge.nix
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
url ? null,
|
||||||
|
hash ? null,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
modpack = pkgs.fetchzip {
|
||||||
|
inherit url hash;
|
||||||
|
stripRoot = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
variablesStr = builtins.readFile "${modpack}/variables.txt";
|
||||||
|
variableLines =
|
||||||
|
builtins.filter (l: l != "" && (lib.strings.elemAt (lib.stringToCharacters l) 0) != "#")
|
||||||
|
(lib.strings.splitString "\n" variablesStr);
|
||||||
|
|
||||||
|
stripQuotes = s:
|
||||||
|
if builtins.match "^\".*\"$" s != null
|
||||||
|
then builtins.substring 1 (builtins.stringLength s - 2) s
|
||||||
|
else s;
|
||||||
|
|
||||||
|
parseLine = line: let
|
||||||
|
parts = lib.strings.splitString "=" line;
|
||||||
|
in {
|
||||||
|
name = builtins.elemAt parts 0;
|
||||||
|
value = stripQuotes (builtins.concatStringsSep "=" (builtins.tail parts));
|
||||||
|
};
|
||||||
|
|
||||||
|
variables = builtins.listToAttrs (map parseLine variableLines);
|
||||||
|
in {
|
||||||
|
inherit variables;
|
||||||
|
root = modpack;
|
||||||
|
mods = "${modpack}/mods";
|
||||||
|
config = "${modpack}/config";
|
||||||
|
}
|
||||||
46
modules/services/minecraft-server/minecraft-server.nix
Normal file
46
modules/services/minecraft-server/minecraft-server.nix
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
flake.nixosModules.minecraft-server = {
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.hive.minecraft-server;
|
||||||
|
|
||||||
|
modpack = pkgs.callPackage ./_loadCurseForge.nix {
|
||||||
|
url = "https://mediafilez.forgecdn.net/files/7765/203/BMC3_Server_Pack_v44.zip";
|
||||||
|
hash = "sha256-doqPzo9fhYM9ng/3RO6OPqhKA2ibfoaKx3Es7M0lpuU=";
|
||||||
|
};
|
||||||
|
|
||||||
|
mcVersion = modpack.variables.MINECRAFT_VERSION;
|
||||||
|
loader = lib.toLower modpack.variables.MODLOADER;
|
||||||
|
loaderVersion = modpack.variables.MODLOADER_VERSION;
|
||||||
|
serverVersion = lib.replaceStrings ["."] ["_"] "${loader}-${mcVersion}";
|
||||||
|
in {
|
||||||
|
options.hive.minecraft-server = {
|
||||||
|
enable = lib.mkEnableOption "Enable BMC3 server";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.minecraft-servers = {
|
||||||
|
enable = true;
|
||||||
|
eula = true;
|
||||||
|
openFirewall = true;
|
||||||
|
|
||||||
|
servers.bmc3 = lib.optionalAttrs cfg.enable {
|
||||||
|
enable = true;
|
||||||
|
autoStart = false;
|
||||||
|
package = pkgs."${loader}Servers".${serverVersion}.override {inherit loaderVersion;};
|
||||||
|
jvmOpts = modpack.variables.JAVA_ARGS;
|
||||||
|
symlinks = {
|
||||||
|
"mods" = "${modpack.root}/mods";
|
||||||
|
};
|
||||||
|
serverProperties = {
|
||||||
|
motd = "Woher kommt der Stein?";
|
||||||
|
white-list = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
136
modules/services/nextcloud-instance.nix
Normal file
136
modules/services/nextcloud-instance.nix
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
{
|
||||||
|
flake.nixosModules.nextcloud-instance = {
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.hive.nextcloud-instance;
|
||||||
|
in {
|
||||||
|
options.hive.nextcloud-instance = {
|
||||||
|
enable = lib.mkEnableOption "Enable the Nextcloud instance";
|
||||||
|
|
||||||
|
instanceFQDN = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "nextcloud.example.com";
|
||||||
|
description = "Fully qualified domain name of the Nextcloud instance";
|
||||||
|
};
|
||||||
|
|
||||||
|
ssl = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Use SSL and auto-update certificates";
|
||||||
|
};
|
||||||
|
|
||||||
|
adminPasswordFile = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
example = "/etc/nc-admin-pass.txt";
|
||||||
|
description = "Path to the file containing the Nextcloud admin password";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.nextcloud = {
|
||||||
|
# Instance
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.nextcloud33;
|
||||||
|
hostName = cfg.instanceFQDN;
|
||||||
|
https = cfg.ssl;
|
||||||
|
configureRedis = true;
|
||||||
|
|
||||||
|
# DB
|
||||||
|
config.dbtype = "pgsql";
|
||||||
|
config.dbhost = "/run/postgresql";
|
||||||
|
config.adminpassFile = cfg.adminPasswordFile;
|
||||||
|
|
||||||
|
#Mail
|
||||||
|
settings = {
|
||||||
|
mail_smtpmode = "sendmail";
|
||||||
|
mail_sendmailmode = "pipe";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Apps
|
||||||
|
extraAppsEnable = true;
|
||||||
|
extraApps = {
|
||||||
|
inherit
|
||||||
|
(config.services.nextcloud.package.packages.apps)
|
||||||
|
calendar
|
||||||
|
contacts
|
||||||
|
tasks
|
||||||
|
;
|
||||||
|
drop_account = pkgs.fetchNextcloudApp {
|
||||||
|
sha256 = "sha256-J+bZVNIb/MokuTYQu8RBKdnZFakh180pa1pW5KHlC80=";
|
||||||
|
url = "https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-3.0.0.tar.gz";
|
||||||
|
license = "agpl3Only";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Raise Upload limit
|
||||||
|
maxUploadSize = "20G";
|
||||||
|
|
||||||
|
# Preview settings (video may be a security risk)
|
||||||
|
settings = {
|
||||||
|
enable_previews = true;
|
||||||
|
enabledPreviewProviders = [
|
||||||
|
"OC\\Preview\\BMP"
|
||||||
|
"OC\\Preview\\GIF"
|
||||||
|
"OC\\Preview\\JPEG"
|
||||||
|
"OC\\Preview\\Krita"
|
||||||
|
"OC\\Preview\\MarkDown"
|
||||||
|
"OC\\Preview\\MP3"
|
||||||
|
"OC\\Preview\\OpenDocument"
|
||||||
|
"OC\\Preview\\PNG"
|
||||||
|
"OC\\Preview\\TXT"
|
||||||
|
"OC\\Preview\\XBitmap"
|
||||||
|
"OC\\Preview\\Movie"
|
||||||
|
"OC\\Preview\\MP4"
|
||||||
|
"OC\\Preview\\AVI"
|
||||||
|
"OC\\Preview\\MKV"
|
||||||
|
];
|
||||||
|
preview_ffmpeg_path = "${pkgs.ffmpeg}/bin/ffmpeg";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Fallback server with only 403
|
||||||
|
services.nginx.virtualHosts.${config.networking.domain} = lib.mkDefault {
|
||||||
|
default = true;
|
||||||
|
locations."/".return = 403;
|
||||||
|
forceSSL = cfg.ssl;
|
||||||
|
enableACME = cfg.ssl;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Webserver setup with optional SSL
|
||||||
|
services.nginx.virtualHosts.${cfg.instanceFQDN} =
|
||||||
|
if cfg.ssl
|
||||||
|
then {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
security.acme = lib.mkIf cfg.ssl {
|
||||||
|
acceptTerms = true;
|
||||||
|
defaults.email = "jonas.roeger+acme@gmail.com";
|
||||||
|
};
|
||||||
|
networking.firewall.allowedTCPPorts = [80] ++ lib.optional cfg.ssl 443;
|
||||||
|
|
||||||
|
# DB setup
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = ["nextcloud"];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "nextcloud";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user