Compare commits
No commits in common. "master" and "v0.1" have entirely different histories.
BIN
.README.md.swp
BIN
.README.md.swp
Binary file not shown.
68
README.md
68
README.md
|
@ -1,68 +0,0 @@
|
||||||
# Server nixos configuration
|
|
||||||
|
|
||||||
This is the configuration running on my homebrew server.
|
|
||||||
It is perfect in and no other config is in any way shape or form better.
|
|
||||||
|
|
||||||
|
|
||||||
# Features
|
|
||||||
|
|
||||||
- Forgejo git instance
|
|
||||||
- Vaultwarden password manager
|
|
||||||
- Jellyfin media server
|
|
||||||
- Sonnar, Radarr, Jackett and transmission auto-torrenting setup in declarative [astro/microvm](https://github.com/astro/microvm.nix) virtual machine behind a VPN.
|
|
||||||
- ZFS RaidZ (Raid5) for data resilience with automated emails for failed drives
|
|
||||||
- Self-hosted mail server for sending emails
|
|
||||||
- Simple file structure for easy extension
|
|
||||||
|
|
||||||
|
|
||||||
# How to Install
|
|
||||||
|
|
||||||
## Prepare device
|
|
||||||
|
|
||||||
Install the [nixos boot ISO](https://nixos.org/download/) and run it on your device.
|
|
||||||
Once booted run
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ sudo passwd
|
|
||||||
$ ip a
|
|
||||||
```
|
|
||||||
|
|
||||||
to set a password for the `nix` user and display your ip.
|
|
||||||
Once done you can ssh into the device and generate a nix hardware config with
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ ssh nix@<ip>
|
|
||||||
$ sudo mkdir /mnt
|
|
||||||
$ sudo nixos-generate-config --root /mnt --no-filesystem
|
|
||||||
```
|
|
||||||
|
|
||||||
This will generate the file `/mnt/hardware-config.nix` that you can then copy to your
|
|
||||||
computer.
|
|
||||||
|
|
||||||
|
|
||||||
## Install configuration
|
|
||||||
|
|
||||||
### Prepare repo
|
|
||||||
|
|
||||||
1. Clone the repo
|
|
||||||
- `git clone https://git.spoodythe.one/spoody/server-configuration.git`
|
|
||||||
1. Copy the `hardware-configuration.nix` from your device to the repo folder.
|
|
||||||
- `scp nix@<ip>:/mnt/hardware-configuration.nix /path/to/repo/hardware-configuration.nix`
|
|
||||||
1. Add/change the device configuration in `flake.nix`
|
|
||||||
- This includes configuring which (if any) disks should be included in the raid array, as well as which disk is the main root disk.
|
|
||||||
|
|
||||||
|
|
||||||
### Install remotely
|
|
||||||
|
|
||||||
Run the command
|
|
||||||
|
|
||||||
```sh
|
|
||||||
nix run github:nix-community/nixos-anywhere -- --flake '.#<your configuration>' --target-host nixos@<ip>
|
|
||||||
```
|
|
||||||
|
|
||||||
This will automatically install the configuration to your server.
|
|
||||||
|
|
||||||
|
|
||||||
## Copy configuration to server
|
|
||||||
|
|
||||||
Once the configuration has been installed push your modified repo to a git service and pull it on the server.
|
|
|
@ -8,23 +8,26 @@
|
||||||
./services/nginx.nix
|
./services/nginx.nix
|
||||||
./services/openssh.nix
|
./services/openssh.nix
|
||||||
./services/forgejo.nix
|
./services/forgejo.nix
|
||||||
|
# ./services/nextcloud.nix
|
||||||
|
# ./services/seafile.nix
|
||||||
./services/vaultwarden.nix
|
./services/vaultwarden.nix
|
||||||
./services/jellyfin.nix
|
./services/jellyfin.nix
|
||||||
./services/website.nix
|
./services/website.nix
|
||||||
./services/mailserver.nix
|
./services/mailserver.nix
|
||||||
./services/fail2ban.nix
|
./services/fail2ban.nix
|
||||||
./services/zed.nix # IMPORTANTE
|
|
||||||
./services/auto-torrent.nix
|
|
||||||
./services/misc.nix
|
|
||||||
|
|
||||||
./services/website.nix
|
./services/zed.nix # IMPORTANTE
|
||||||
|
|
||||||
|
./services/auto-torrent.nix
|
||||||
|
|
||||||
|
./services/misc.nix
|
||||||
|
|
||||||
./modules/age.nix
|
./modules/age.nix
|
||||||
./modules/git.nix
|
./modules/git.nix
|
||||||
./modules/nix-settings.nix
|
./modules/nix-settings.nix
|
||||||
./modules/zfs.nix
|
./modules/zfs.nix
|
||||||
./modules/microvm.nix
|
|
||||||
|
|
||||||
|
(import ./modules/microvm.nix {routed = true;})
|
||||||
(import ./modules/networking-shared.nix {hostname = "server";})
|
(import ./modules/networking-shared.nix {hostname = "server";})
|
||||||
(import ./modules/users.nix {main-user = "baritone";})
|
(import ./modules/users.nix {main-user = "baritone";})
|
||||||
];
|
];
|
||||||
|
@ -39,11 +42,21 @@
|
||||||
# Enable microcode updates
|
# Enable microcode updates
|
||||||
hardware.enableRedistributableFirmware = true;
|
hardware.enableRedistributableFirmware = true;
|
||||||
|
|
||||||
|
# programs.zsh = {
|
||||||
|
# enable = true;
|
||||||
|
# enableGlobalCompInit = true;
|
||||||
|
# shellAliases = {
|
||||||
|
# "nrb" = "sudo nixos-rebuild switch --flake /etc/nixos";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
wget
|
wget
|
||||||
curl
|
curl
|
||||||
git
|
git
|
||||||
vim
|
vim
|
||||||
|
|
||||||
|
inputs.agenix.packages."${system}".default
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.nano.enable = false;
|
programs.nano.enable = false;
|
||||||
|
|
28
disko.nix
28
disko.nix
|
@ -8,14 +8,12 @@
|
||||||
disko.devices = {
|
disko.devices = {
|
||||||
disk =
|
disk =
|
||||||
{
|
{
|
||||||
# Main SSD where /nix/store /etc /boot etc. is located.
|
|
||||||
main = {
|
main = {
|
||||||
type = "disk";
|
type = "disk";
|
||||||
device = root-disk;
|
device = root-disk;
|
||||||
content = {
|
content = {
|
||||||
type = "gpt";
|
type = "gpt";
|
||||||
partitions = {
|
partitions = {
|
||||||
# Define a 512 megabyte boot partition
|
|
||||||
boot = {
|
boot = {
|
||||||
size = "512M";
|
size = "512M";
|
||||||
type = "EF00";
|
type = "EF00";
|
||||||
|
@ -26,7 +24,6 @@
|
||||||
mountOptions = ["umask=0077"];
|
mountOptions = ["umask=0077"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# If the swap argument is defined then create a swap partition of the given size
|
|
||||||
swap = lib.mkIf (swap-size != -1) {
|
swap = lib.mkIf (swap-size != -1) {
|
||||||
size = swap-size;
|
size = swap-size;
|
||||||
content = {
|
content = {
|
||||||
|
@ -35,7 +32,6 @@
|
||||||
resumeDevice = true;
|
resumeDevice = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# Finally allocate the rest of the disk as a zfs device
|
|
||||||
root = {
|
root = {
|
||||||
size = "100%";
|
size = "100%";
|
||||||
content = {
|
content = {
|
||||||
|
@ -66,13 +62,12 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
zpool = {
|
zpool = {
|
||||||
# Set up zroot pool
|
|
||||||
zroot = {
|
zroot = {
|
||||||
type = "zpool";
|
type = "zpool";
|
||||||
rootFsOptions = {
|
rootFsOptions = {
|
||||||
mountpoint = "none";
|
mountpoint = "none";
|
||||||
acltype = "posixacl"; # POSIX compliant file permissions
|
acltype = "posixacl";
|
||||||
xattr = "sa"; # Store attributes in inodes to reduce disk reads
|
xattr = "sa";
|
||||||
};
|
};
|
||||||
|
|
||||||
datasets = {
|
datasets = {
|
||||||
|
@ -88,17 +83,16 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# If any disks where defined to be in the raid we set up the raid5 pool
|
|
||||||
raid5 = lib.mkIf (builtins.length raid-disks > 0) {
|
raid5 = lib.mkIf (builtins.length raid-disks > 0) {
|
||||||
type = "zpool";
|
type = "zpool";
|
||||||
mode = "raidz";
|
mode = "raidz";
|
||||||
|
|
||||||
rootFsOptions = {
|
rootFsOptions = {
|
||||||
compression = "zstd"; # Compress filesystem for more storage
|
compression = "zstd";
|
||||||
mountpoint = "none"; # Dont mount the zfs pool anywhere
|
mountpoint = "none";
|
||||||
acltype = "posixacl"; # POSIX compliant file permissions
|
acltype = "posixacl";
|
||||||
xattr = "sa"; # Store attributes in inodes to reduce disk reads
|
xattr = "sa";
|
||||||
"com.sun:auto-snapshot" = "true"; # Never a bad idea to have backups
|
"com.sun:auto-snapshot" = "true";
|
||||||
};
|
};
|
||||||
|
|
||||||
datasets = {
|
datasets = {
|
||||||
|
@ -118,10 +112,10 @@
|
||||||
type = "zfs_fs";
|
type = "zfs_fs";
|
||||||
mountpoint = "/opt";
|
mountpoint = "/opt";
|
||||||
};
|
};
|
||||||
# media = {
|
media = {
|
||||||
# type = "zfs_fs";
|
type = "zfs_fs";
|
||||||
# mountpoint = "/media";
|
mountpoint = "/media";
|
||||||
# };
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
18
flake.lock
18
flake.lock
|
@ -143,11 +143,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1743295846,
|
"lastModified": 1742326330,
|
||||||
"narHash": "sha256-hKKz07d4RV9gzxzE5Qu3RQWX8a7XpzRrP5timoxoGRQ=",
|
"narHash": "sha256-Tumt3tcMXJniSh7tw2gW+WAnVLeB3WWm+E+yYFnLBXo=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "717030011980e9eb31eb8ce011261dd532bce92c",
|
"rev": "22a36aa709de7dd42b562a433b9cefecf104a6ee",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -165,11 +165,11 @@
|
||||||
"spectrum": "spectrum"
|
"spectrum": "spectrum"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1743083165,
|
"lastModified": 1741893540,
|
||||||
"narHash": "sha256-Fz7AiCJWtoWZ2guJwO3B1h3RuJxYWaCzFIqY0Kmkyrs=",
|
"narHash": "sha256-NEsR+FQ+AsY4cOZ3OL69JVdPTAYzSzBqeAhHGRRuDGk=",
|
||||||
"owner": "astro",
|
"owner": "astro",
|
||||||
"repo": "microvm.nix",
|
"repo": "microvm.nix",
|
||||||
"rev": "773d5a04e2e10ca7b412270dea11276a496e1b61",
|
"rev": "5bbc126db87b5ffc36394df630eead403c48fac8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -180,11 +180,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1743095683,
|
"lastModified": 1742288794,
|
||||||
"narHash": "sha256-gWd4urRoLRe8GLVC/3rYRae1h+xfQzt09xOfb0PaHSk=",
|
"narHash": "sha256-Txwa5uO+qpQXrNG4eumPSD+hHzzYi/CdaM80M9XRLCo=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5e5402ecbcb27af32284d4a62553c019a3a49ea6",
|
"rev": "b6eaf97c6960d97350c584de1b6dcff03c9daf42",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
{
|
{config, ...}: {
|
||||||
config,
|
# This is where the age files go
|
||||||
pkgs,
|
# age.secrets.nextcloud.file = ../secrets/nextcloud.age;
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
age.identityPaths = [
|
|
||||||
"/home/baritone/.ssh/id_ed25519"
|
|
||||||
];
|
|
||||||
age.secrets = {
|
|
||||||
forgejo-runner-token.file = ../secrets/forgejo-runner-token.age;
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [inputs.agenix.packages."${pkgs.system}".default];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{routed ? false}: {
|
||||||
pkgs,
|
pkgs,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
|
|
|
@ -34,8 +34,5 @@
|
||||||
"nrb" = "sudo nixos-rebuild switch --flake /etc/nixos";
|
"nrb" = "sudo nixos-rebuild switch --flake /etc/nixos";
|
||||||
"vmr" = "rm ~/.ssh/known_hosts; ssh root@10.0.0.1";
|
"vmr" = "rm ~/.ssh/known_hosts; ssh root@10.0.0.1";
|
||||||
};
|
};
|
||||||
shellAliases = {
|
|
||||||
"fucking" = "sudo";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,8 @@
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
zfs
|
zfs
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# Microvm be fucking shit up
|
||||||
|
# fileSystems."/nix/store".fsType = lib.mkForce "zfs";
|
||||||
|
# fileSystems."/nix/store".device = lib.mkForce "zroot/nix/store";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
age-encryption.org/v1
|
|
||||||
-> ssh-ed25519 rgw77A B/0cZTeHin54r5rLOPknrID5HqDdXUP1f3n6q28B11s
|
|
||||||
I8lGmJNvkJQQUlWD8fbCt+IuYisKhoVb59ulqQZsGJw
|
|
||||||
--- 5qC6VjzF8ldbN+AuD+G5y8ABxl+hqD1mt8QyEgVxrjI
|
|
||||||
rêÊcåºÃMï·Ö UÞ;œm0à6kª°;‚ª-sŸKÿÀÔWM;·ã_Š<5F>&<26>Yk\èŒMNê1¨qO¨¤hM7kA1m•1
|
|
|
@ -2,5 +2,4 @@ let
|
||||||
public-keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC562Woe/yT/3dNVceN9rKPJQcvgTFzIhJVdVGv7sqn1 baritone@server"];
|
public-keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC562Woe/yT/3dNVceN9rKPJQcvgTFzIhJVdVGv7sqn1 baritone@server"];
|
||||||
in {
|
in {
|
||||||
"nextcloud.age".publicKeys = public-keys;
|
"nextcloud.age".publicKeys = public-keys;
|
||||||
"forgejo-runner-token.age".publicKeys = public-keys;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,28 +5,14 @@
|
||||||
}: let
|
}: let
|
||||||
lib = pkgs.lib;
|
lib = pkgs.lib;
|
||||||
host = "10.0.${toString vm-index}.1";
|
host = "10.0.${toString vm-index}.1";
|
||||||
|
port = 8989;
|
||||||
ports = {
|
|
||||||
sonarr.port = 8989;
|
|
||||||
radarr.port = 7878;
|
|
||||||
jackett.port = 9117;
|
|
||||||
};
|
|
||||||
|
|
||||||
vm-index = 1;
|
vm-index = 1;
|
||||||
vm-mac = "02:00:00:00:00:02";
|
vm-mac = "02:00:00:00:00:02";
|
||||||
vm-name = "auto-torrent";
|
vm-name = "auto-torrent";
|
||||||
vpn-endpoint = "193.32.248.70";
|
vpn-endpoint = "193.32.248.70";
|
||||||
enable-services = true;
|
enable-services = true;
|
||||||
wg-config = "/mnt/wg.conf";
|
|
||||||
jellyfin-gid = 989;
|
|
||||||
|
|
||||||
ports-list = (pkgs.lib.attrsets.mapAttrsToList (name: value: value.port) ports) ++ [9091];
|
|
||||||
in {
|
in {
|
||||||
microvm.autostart = [vm-name];
|
microvm.autostart = [vm-name];
|
||||||
imports = [
|
|
||||||
./nginx.nix
|
|
||||||
../modules/microvm.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
users.extraUsers.microvm.extraGroups = [
|
users.extraUsers.microvm.extraGroups = [
|
||||||
"jellyfin" # access to media folder
|
"jellyfin" # access to media folder
|
||||||
|
@ -34,7 +20,9 @@ in {
|
||||||
|
|
||||||
system.activationScripts."make-${vm-name}-data-dir" = lib.stringAfter ["var"] ''
|
system.activationScripts."make-${vm-name}-data-dir" = lib.stringAfter ["var"] ''
|
||||||
mkdir -p /var/lib/${vm-name}
|
mkdir -p /var/lib/${vm-name}
|
||||||
# chown -R microvm:jellyfin /var/lib/${vm-name}
|
chmod -R 777 /var/lib/${vm-name}
|
||||||
|
chown -R microvm /var/lib/${vm-name}
|
||||||
|
chmod -R 777 /media
|
||||||
'';
|
'';
|
||||||
|
|
||||||
microvm.vms.${vm-name} = {
|
microvm.vms.${vm-name} = {
|
||||||
|
@ -48,8 +36,6 @@ in {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
time.timeZone = "Europe/Copenhagen";
|
|
||||||
|
|
||||||
# 1gb of memory
|
# 1gb of memory
|
||||||
microvm.mem = 1024;
|
microvm.mem = 1024;
|
||||||
|
|
||||||
|
@ -69,7 +55,7 @@ in {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
tag = "media-dir";
|
tag = "media-dir";
|
||||||
source = "/var/lib/media";
|
source = "/media";
|
||||||
mountPoint = "/media";
|
mountPoint = "/media";
|
||||||
inherit proto;
|
inherit proto;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +101,7 @@ in {
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
type = "oneshot";
|
type = "oneshot";
|
||||||
ExecStart = pkgs.writeShellScript "wgconf.sh" ''
|
ExecStart = pkgs.writeShellScript "wgconf.sh" ''
|
||||||
${pkgs.wireguard-tools}/bin/wg-quick up ${wg-config}
|
${pkgs.wireguard-tools}/bin/wg-quick up /mnt/wg.conf
|
||||||
'';
|
'';
|
||||||
RemainAfterExit = "yes";
|
RemainAfterExit = "yes";
|
||||||
};
|
};
|
||||||
|
@ -133,18 +119,6 @@ in {
|
||||||
programs.nano.enable = lib.mkForce false;
|
programs.nano.enable = lib.mkForce false;
|
||||||
programs.vim.enable = true;
|
programs.vim.enable = true;
|
||||||
|
|
||||||
# Fix permissions with groups
|
|
||||||
users.users = {
|
|
||||||
sonarr.extraGroups = ["jellyfin"];
|
|
||||||
radarr.extraGroups = ["jellyfin"];
|
|
||||||
transmission.extraGroups = ["jellyfin"];
|
|
||||||
jackett.extraGroups = ["jellyfin"];
|
|
||||||
};
|
|
||||||
|
|
||||||
users.groups.jellyfin = {
|
|
||||||
gid = jellyfin-gid;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Services
|
# Services
|
||||||
services.sonarr = pkgs.lib.mkIf enable-services {
|
services.sonarr = pkgs.lib.mkIf enable-services {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -164,25 +138,11 @@ in {
|
||||||
|
|
||||||
services.transmission = pkgs.lib.mkIf enable-services {
|
services.transmission = pkgs.lib.mkIf enable-services {
|
||||||
enable = true;
|
enable = true;
|
||||||
openPeerPorts = true;
|
openFirewall = true;
|
||||||
openRPCPort = true;
|
|
||||||
home = "/mnt/transmission";
|
home = "/mnt/transmission";
|
||||||
webHome = "${pkgs.flood-for-transmission}";
|
settings.download-dir = "/mnt/transmission";
|
||||||
settings = {
|
settings.incomplete-dir = "/mnt/transmission/.incomplete";
|
||||||
download-dir = "/media/.transmission/";
|
|
||||||
incomplete-dir = "/media/.transmission/.incomplete";
|
|
||||||
peer-port-random-low = 65500;
|
|
||||||
peer-port-random-high = 65535;
|
|
||||||
peer-port-random-on-start = true;
|
|
||||||
download-queue-enabled = false;
|
|
||||||
|
|
||||||
rpc-authentication-required = false;
|
|
||||||
rpc-bind-address = "0.0.0.0";
|
|
||||||
rpc-host-whitelist = builtins.concatStringsSep "," [host "127.0.0.1" "10.0.101.10" "10.0.${toString vm-index}.254"];
|
|
||||||
rpc-whitelist = builtins.concatStringsSep "," [host "127.0.0.1" "10.0.101.10" "10.0.${toString vm-index}.254"];
|
|
||||||
};
|
|
||||||
downloadDirPermissions = "775";
|
downloadDirPermissions = "775";
|
||||||
performanceNetParameters = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# debugging
|
# debugging
|
||||||
|
@ -209,41 +169,73 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Add virtual hosts for all the different services running in the vm
|
# Sonarr
|
||||||
services.nginx.virtualHosts = builtins.listToAttrs (pkgs.lib.attrsets.mapAttrsToList (
|
services.nginx.virtualHosts."sonarr.spoodythe.one" = {
|
||||||
name: value: {
|
addSSL = true;
|
||||||
name = "${name}.spoodythe.one";
|
enableACME = true;
|
||||||
value = {
|
listen = [
|
||||||
addSSL = true;
|
{
|
||||||
enableACME = true;
|
inherit port;
|
||||||
listen = [
|
addr = "0.0.0.0";
|
||||||
{
|
ssl = false;
|
||||||
port = value.port;
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
ssl = false;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
port = 443;
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
ssl = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://${host}:${toString value.port}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
)
|
{
|
||||||
ports);
|
port = 443;
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${host}:${toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# Forward transmission web port to vm
|
# Radarr
|
||||||
networking.nat.forwardPorts = [
|
services.nginx.virtualHosts."radarr.spoodythe.one" = let
|
||||||
{
|
port = 7878;
|
||||||
sourcePort = 9091;
|
in {
|
||||||
destination = "${host}:9091";
|
addSSL = true;
|
||||||
}
|
enableACME = true;
|
||||||
];
|
listen = [
|
||||||
|
{
|
||||||
|
inherit port;
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
ssl = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
port = 443;
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${host}:${toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = ports-list;
|
# Jackett
|
||||||
networking.firewall.allowedUDPPorts = ports-list;
|
services.nginx.virtualHosts."jackett.spoodythe.one" = let
|
||||||
|
port = 9117;
|
||||||
|
in {
|
||||||
|
addSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
inherit port;
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
ssl = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
port = 443;
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${host}:${toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [port 9117 7878 9696 80 433];
|
||||||
|
networking.firewall.allowedUDPPorts = [port 9117 7878 9696 80 433];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
{...}: let
|
|
||||||
port = 6167;
|
|
||||||
host = "127.0.0.1";
|
|
||||||
domain = "matrix.spoodythe.one";
|
|
||||||
mb = 1024 * 1024;
|
|
||||||
max-request-size = 20;
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
./nginx.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
services.conduwuit = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
global = {
|
|
||||||
port = [port];
|
|
||||||
address = [host];
|
|
||||||
server_name = domain;
|
|
||||||
max_request_size = max-request-size * mb;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."${domain}" = {
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
listen = [
|
|
||||||
{
|
|
||||||
port = 443;
|
|
||||||
ssl = true;
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
port = 8448;
|
|
||||||
ssl = true;
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://${host}:${toString port}";
|
|
||||||
extraConfig = ''
|
|
||||||
client_max_body_size ${toString max-request-size}M;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
locations."/_matrix" = {
|
|
||||||
proxyPass = "http://${host}:${toString port}";
|
|
||||||
extraConfig = ''
|
|
||||||
client_max_body_size ${toString max-request-size}M;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Open port so i can access it on my local network
|
|
||||||
networking.firewall.allowedTCPPorts = [port 8448];
|
|
||||||
networking.firewall.allowedUDPPorts = [port 8448];
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{...}: {
|
|
||||||
virtualisation.docker = {
|
|
||||||
enable = true;
|
|
||||||
storageDriver = "zfs";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -3,34 +3,8 @@
|
||||||
lib,
|
lib,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: let
|
}: {
|
||||||
jails = {
|
services.fail2ban = {
|
||||||
forgejo = mkJail "forgejo" "^.*Failed authentication attempt for .* from <ADDR>.*$";
|
|
||||||
jellyfin = mkJail "jellyfin" "^.*Authentication request for .* has been denied \\(IP: <ADDR>\\)\\.";
|
|
||||||
sonarr = mkJail "sonarr" "^.*Auth-Failure ip <ADDR> username.*$";
|
|
||||||
radarr = mkJail "sonarr" "^.*Auth-Failure ip <ADDR> username.*$";
|
|
||||||
vaultwarden = mkJail "vaultwarden" "^.*Username or password is incorrect. Try again. IP: <ADDR>\\. Username: .*$";
|
|
||||||
};
|
|
||||||
|
|
||||||
mkJail = name: filter: {
|
|
||||||
jail.settings = {
|
|
||||||
enabled = true;
|
|
||||||
filter = name;
|
|
||||||
backend = "systemd";
|
|
||||||
port = "80,443";
|
|
||||||
maxretry = 8;
|
|
||||||
bantime = "24h";
|
|
||||||
findtime = "30m";
|
|
||||||
journalmatch = "_SYSTEMD_UNIT=${name}.service";
|
|
||||||
};
|
|
||||||
filter = ''
|
|
||||||
[Definition]
|
|
||||||
failregex = ${filter}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
services.fail2ban = let
|
|
||||||
in {
|
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
bantime = "24h";
|
bantime = "24h";
|
||||||
|
@ -41,34 +15,40 @@ in {
|
||||||
overalljails = true;
|
overalljails = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
jails =
|
jails = {
|
||||||
{
|
dovecot = lib.mkIf config.services.dovecot2.enable {
|
||||||
dovecot = lib.mkIf config.services.dovecot2.enable {
|
settings = {
|
||||||
settings = {
|
# block IPs which failed to log-in
|
||||||
# block IPs which failed to log-in
|
# aggressive mode add blocking for aborted connections
|
||||||
# aggressive mode add blocking for aborted connections
|
filter = "dovecot[mode=aggressive]";
|
||||||
filter = "dovecot[mode=aggressive]";
|
maxretry = 3;
|
||||||
maxretry = 3;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
// (lib.attrsets.mapAttrs (name: value: value.jail) jails);
|
|
||||||
|
jellyfin = lib.mkIf config.services.jellyfin.enable {
|
||||||
|
settings = {
|
||||||
|
filter = "jellyfin";
|
||||||
|
backend = "auto";
|
||||||
|
enabled = true;
|
||||||
|
port = "8096,8920";
|
||||||
|
maxretry = 3;
|
||||||
|
bantime = 86400;
|
||||||
|
findtime = 43200;
|
||||||
|
logpath = "/var/lib/jellyfin/log/*.log";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.etc =
|
environment.etc = {
|
||||||
{
|
"fail2ban/filter.d/jellyfin.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
|
||||||
# Defines a filter that detects URL probing by reading the Nginx access log
|
[Definition]
|
||||||
"fail2ban/filter.d/nginx-url-probe.local".text = lib.mkDefault (lib.mkAfter ''
|
failregex = ^.*Authentication request for .* has been denied \(IP: <ADDR>\)\.
|
||||||
[Definition]
|
'');
|
||||||
failregex = ^<HOST>.*(GET /(wp-|admin|boaform|phpmyadmin|\.env|\.git)|\.(dll|so|cfm|asp)|(\?|&)(=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000|=PHPE9568F36-D428-11d2-A769-00AA001ACF42|=PHPE9568F35-D428-11d2-A769-00AA001ACF42|=PHPE9568F34-D428-11d2-A769-00AA001ACF42)|\\x[0-9a-zA-Z]{2})
|
# Defines a filter that detects URL probing by reading the Nginx access log
|
||||||
'');
|
"fail2ban/filter.d/nginx-url-probe.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
|
||||||
}
|
[Definition]
|
||||||
// (with lib.attrsets;
|
failregex = ^<HOST>.*(GET /(wp-|admin|boaform|phpmyadmin|\.env|\.git)|\.(dll|so|cfm|asp)|(\?|&)(=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000|=PHPE9568F36-D428-11d2-A769-00AA001ACF42|=PHPE9568F35-D428-11d2-A769-00AA001ACF42|=PHPE9568F34-D428-11d2-A769-00AA001ACF42)|\\x[0-9a-zA-Z]{2})
|
||||||
mapAttrs' (
|
'');
|
||||||
name: value:
|
};
|
||||||
nameValuePair
|
|
||||||
"fail2ban/filter.d/${name}.local"
|
|
||||||
{text = lib.mkDefault (lib.mkAfter value.filter);}
|
|
||||||
)
|
|
||||||
jails);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,6 @@
|
||||||
host = "127.0.0.1";
|
host = "127.0.0.1";
|
||||||
port = 6969;
|
port = 6969;
|
||||||
in {
|
in {
|
||||||
imports = [
|
|
||||||
./nginx.nix
|
|
||||||
./gitea-actions-runner.nix
|
|
||||||
];
|
|
||||||
services.forgejo = {
|
services.forgejo = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
|
@ -17,10 +13,6 @@ in {
|
||||||
APP_NAME = "An idiot admires complexity. A genius admires simplicity";
|
APP_NAME = "An idiot admires complexity. A genius admires simplicity";
|
||||||
};
|
};
|
||||||
|
|
||||||
repository = {
|
|
||||||
ENABLE_PUSH_CREATE_USER = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
DOMAIN = "git.spoodythe.one";
|
DOMAIN = "git.spoodythe.one";
|
||||||
HTTP_PORT = port;
|
HTTP_PORT = port;
|
||||||
|
@ -46,4 +38,8 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Open port 80 and 443 for reverse proxy
|
||||||
|
networking.firewall.allowedTCPPorts = [80 443];
|
||||||
|
networking.firewall.allowedUDPPorts = [80 443];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
|
||||||
./docker.nix
|
|
||||||
../modules/age.nix
|
|
||||||
];
|
|
||||||
services.gitea-actions-runner = {
|
|
||||||
package = pkgs.forgejo-runner;
|
|
||||||
instances = {
|
|
||||||
agurk = {
|
|
||||||
enable = true;
|
|
||||||
name = "agurk";
|
|
||||||
url = "http://127.0.0.1:${toString config.services.forgejo.settings.server.HTTP_PORT}";
|
|
||||||
tokenFile = config.age.secrets.forgejo-runner-token.path;
|
|
||||||
labels = [
|
|
||||||
"native:host"
|
|
||||||
];
|
|
||||||
hostPackages = pkgs.lib.attrValues {
|
|
||||||
inherit
|
|
||||||
(pkgs)
|
|
||||||
nix
|
|
||||||
nodejs
|
|
||||||
git
|
|
||||||
bash
|
|
||||||
fd
|
|
||||||
ripgrep
|
|
||||||
openssh
|
|
||||||
;
|
|
||||||
};
|
|
||||||
settings = {
|
|
||||||
log.level = "info";
|
|
||||||
runner = {
|
|
||||||
file = ".runner";
|
|
||||||
capacity = 2;
|
|
||||||
timeout = "3h";
|
|
||||||
insecure = false;
|
|
||||||
fetch_timeout = "5s";
|
|
||||||
fetch_interval = "2s";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
hval = pkgs.lib.mkIf false {
|
|
||||||
enable = true;
|
|
||||||
name = "hval";
|
|
||||||
url = "http://host.docker.internal:${toString config.services.forgejo.settings.server.HTTP_PORT}";
|
|
||||||
tokenFile = config.age.secrets.forgejo-runner-token.path;
|
|
||||||
labels = [
|
|
||||||
docker:docker://node:16-bullseye
|
|
||||||
];
|
|
||||||
hostPackages = pkgs.lib.attrValues {
|
|
||||||
inherit
|
|
||||||
(pkgs)
|
|
||||||
nix
|
|
||||||
nodejs
|
|
||||||
git
|
|
||||||
bash
|
|
||||||
fd
|
|
||||||
ripgrep
|
|
||||||
openssh
|
|
||||||
;
|
|
||||||
};
|
|
||||||
settings = {
|
|
||||||
log.level = "info";
|
|
||||||
runner = {
|
|
||||||
file = ".runner";
|
|
||||||
capacity = 2;
|
|
||||||
timeout = "3h";
|
|
||||||
insecure = false;
|
|
||||||
fetch_timeout = "5s";
|
|
||||||
fetch_interval = "2s";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
system.activationScripts."make-gitea-runner-dir" = pkgs.lib.stringAfter ["var"] ''
|
|
||||||
mkdir -p /var/lib/gitea-runner/
|
|
||||||
# chown -R microvm:jellyfin /var/lib/gitea-runner
|
|
||||||
'';
|
|
||||||
|
|
||||||
# systemd.services = builtins.listToAttrs (pkgs.lib.attrsets.mapAttrsToList (
|
|
||||||
# name: value: {
|
|
||||||
# name = "gitea-runner-${name}";
|
|
||||||
# value = {
|
|
||||||
# serviceConfig.ReadWritePaths = "/srv/web";
|
|
||||||
# };
|
|
||||||
# }
|
|
||||||
# ) config.services.gitea-actions-runner.instances);
|
|
||||||
}
|
|
44
services/homepage.nix
Normal file
44
services/homepage.nix
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{...}: let
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 8082;
|
||||||
|
in {
|
||||||
|
services.homepage-dashboard = {
|
||||||
|
enable = true;
|
||||||
|
listenPort = port;
|
||||||
|
openFirewall = false;
|
||||||
|
widgets = [
|
||||||
|
{
|
||||||
|
resources = {
|
||||||
|
cpu = true;
|
||||||
|
disk = "/";
|
||||||
|
memory = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
services = [
|
||||||
|
{
|
||||||
|
"WebUI" = [
|
||||||
|
{
|
||||||
|
"Jellyfin" = {
|
||||||
|
description = "Jellyfin";
|
||||||
|
href = "https://media.spoodythe.one";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."dashboard.spoodythe.one" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${host}:${toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open port 80 and 443 for reverse proxy
|
||||||
|
networking.firewall.allowedTCPPorts = [80 443];
|
||||||
|
networking.firewall.allowedUDPPorts = [80 443];
|
||||||
|
}
|
|
@ -6,9 +6,35 @@
|
||||||
}: let
|
}: let
|
||||||
host = "127.0.0.1";
|
host = "127.0.0.1";
|
||||||
port = 8096;
|
port = 8096;
|
||||||
gid = 989;
|
jellyfin =
|
||||||
|
if config.services.mullvad-vpn.enable == true
|
||||||
|
then
|
||||||
|
pkgs.callPackage ({...}:
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
pname = "jellyfin-excluded";
|
||||||
|
version = "1.0.0";
|
||||||
|
|
||||||
|
phases = ["installPhase"];
|
||||||
|
|
||||||
|
buildInputs = [pkgs.jellyfin];
|
||||||
|
|
||||||
|
# Define the install phase
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
# Create a wrapper script
|
||||||
|
echo "${pkgs.mullvad-vpn}/bin/mullvad-exclude ${pkgs.jellyfin}/bin/jellyfin \"$@\"" > $out/bin/jellyfin-excluded
|
||||||
|
chmod +x $out/bin/jellyfin-excluded
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Specify the output
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
description = "A wrapper for the hello command";
|
||||||
|
mainProgram = "jellyfin-excluded";
|
||||||
|
license = licenses.mit;
|
||||||
|
};
|
||||||
|
}) {}
|
||||||
|
else pkgs.jellyfin;
|
||||||
in {
|
in {
|
||||||
imports = [./nginx.nix];
|
|
||||||
# Enable VAAPI
|
# Enable VAAPI
|
||||||
config.nixpkgs.config.packageOverrides = pkgs: {
|
config.nixpkgs.config.packageOverrides = pkgs: {
|
||||||
vaapiIntel = pkgs.vaapiIntel.override {enableHybridCodec = true;};
|
vaapiIntel = pkgs.vaapiIntel.override {enableHybridCodec = true;};
|
||||||
|
@ -24,19 +50,17 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# Set declarative gid
|
|
||||||
config.users.groups.jellyfin.gid = gid;
|
|
||||||
|
|
||||||
# Create folder for media
|
# Create folder for media
|
||||||
config.system.activationScripts."jellyfinMediaFolder" = lib.stringAfter ["var"] ''
|
config.system.activationScripts."jellyfinMediaFolder" = lib.stringAfter ["var"] ''
|
||||||
mkdir -p /var/lib/media
|
mkdir -p /media
|
||||||
chmod 770 /var/lib/media
|
chmod -R 775 /media
|
||||||
chown -R jellyfin:jellyfin /var/lib/media
|
chown -R jellyfin:jellyfin /media
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Enable Jellyfin
|
# Enable Jellyfin
|
||||||
config.services.jellyfin = {
|
config.services.jellyfin = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
package = jellyfin;
|
||||||
openFirewall = false; # We want jellyfin behind a reverse proxy
|
openFirewall = false; # We want jellyfin behind a reverse proxy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,7 +78,6 @@ in {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://${host}:${toString port}";
|
proxyPass = "http://${host}:${toString port}";
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
# Websocket support
|
# Websocket support
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
@ -66,7 +89,7 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Open ports for local network access
|
# Open port 80 and 443 for reverse proxy
|
||||||
config.networking.firewall.allowedTCPPorts = [port];
|
config.networking.firewall.allowedTCPPorts = [port 80 443];
|
||||||
config.networking.firewall.allowedUDPPorts = [port];
|
config.networking.firewall.allowedUDPPorts = [port 80 443];
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,17 @@
|
||||||
recommendedOptimisation = true;
|
recommendedOptimisation = true;
|
||||||
recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
recommendedTlsSettings = true;
|
recommendedTlsSettings = true;
|
||||||
|
|
||||||
|
virtualHosts."spoodythe.one" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
default = true;
|
||||||
|
locations."/" = {
|
||||||
|
return = 404;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.acceptTerms = true;
|
security.acme.acceptTerms = true;
|
||||||
security.acme.defaults.email = "snorre@altschul.dk";
|
security.acme.defaults.email = "snorre@altschul.dk";
|
||||||
|
|
||||||
# Open port 80 and 443 for reverse proxy
|
|
||||||
networking.firewall.allowedTCPPorts = [80 443];
|
|
||||||
networking.firewall.allowedUDPPorts = [80 443];
|
|
||||||
}
|
}
|
||||||
|
|
18
services/rtorrent.nix
Normal file
18
services/rtorrent.nix
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{pkgs, ...}: let
|
||||||
|
port = 9091;
|
||||||
|
in {
|
||||||
|
# services.rtorrent = {
|
||||||
|
# enable = true;
|
||||||
|
# dataDir = "/mnt/rtorrent";
|
||||||
|
# user = "rtorrent";
|
||||||
|
# group = "rtorrent";
|
||||||
|
# package = pkgs.jesec-rtorrent;
|
||||||
|
# inherit port;
|
||||||
|
# };
|
||||||
|
|
||||||
|
services.transmission = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = false;
|
||||||
|
settings.rpc-port = port;
|
||||||
|
};
|
||||||
|
}
|
28
services/seafile.nix
Normal file
28
services/seafile.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 8008;
|
||||||
|
in {
|
||||||
|
services.seafile = {
|
||||||
|
enable = true;
|
||||||
|
adminEmail = "snorre@altschul.dk";
|
||||||
|
seahubAddress = "http://${host}:${toString port}";
|
||||||
|
# seafileSettings.fileserver = {
|
||||||
|
# inherit host port;
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
services.nginx.virtualHosts."files.spoodythe.one" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${host}:${toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open port 80 and 443 for reverse proxy
|
||||||
|
networking.firewall.allowedTCPPorts = [80 443];
|
||||||
|
networking.firewall.allowedUDPPorts = [80 443];
|
||||||
|
}
|
189
services/sonarr-old.nix
Executable file
189
services/sonarr-old.nix
Executable file
|
@ -0,0 +1,189 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 8989;
|
||||||
|
vm-index = 1;
|
||||||
|
vm-mac = "00:00:00:00:00:01";
|
||||||
|
vm-name = "necoarc";
|
||||||
|
in {
|
||||||
|
config.microvm.autostart = [vm-name];
|
||||||
|
|
||||||
|
config.users.extraUsers.microvm.extraGroups = [
|
||||||
|
"jellyfin" # access to media folder
|
||||||
|
];
|
||||||
|
|
||||||
|
config.system.activationScripts."make${vm-name}DataDir" = lib.stringAfter ["var"] ''
|
||||||
|
mkdir -p /var/lib/${vm-name}
|
||||||
|
chmod -R 777 /var/lib/${vm-name}
|
||||||
|
chown -R microvm /var/lib/${vm-name}
|
||||||
|
chmod -R 777 /media
|
||||||
|
'';
|
||||||
|
|
||||||
|
# config.networking.wireguard.enable = true;
|
||||||
|
# # config.boot.extraModulePackages = [config.boot.kernelPackages.wireguard];
|
||||||
|
|
||||||
|
# config.networking.wireguard.interfaces.wg0 = {
|
||||||
|
# ips = ["10.75.60.108/32"];
|
||||||
|
# listenPort = 51820;
|
||||||
|
# privateKeyFile = "${./wireguard-secret}";
|
||||||
|
# peers = [
|
||||||
|
# {
|
||||||
|
# publicKey = "TPAIPTgu9jIitgX1Bz5xMCZJ9pRRZTdtZEOIxArO0Hc=";
|
||||||
|
# endpoint = "185.254.75.4:51820";
|
||||||
|
# allowedIPs = ["0.0.0.0/0"];
|
||||||
|
# persistentKeepalive = 25;
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# config.systemd.network.networks.wg0 = {
|
||||||
|
# matchConfig.Name = "wg0";
|
||||||
|
# address = ["10.0.1.${toString vm-index}/24"];
|
||||||
|
# networkConfig = {
|
||||||
|
# IPMasquerade = "ipv4";
|
||||||
|
# IPv4Forwarding = true;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
config.microvm.vms.${vm-name} = {
|
||||||
|
config = {config, ...}: {
|
||||||
|
system.stateVersion = "24.11";
|
||||||
|
# Storage share configuration
|
||||||
|
microvm.shares = [
|
||||||
|
{
|
||||||
|
tag = "ro-store";
|
||||||
|
source = "/nix/store";
|
||||||
|
mountPoint = "/nix/.ro-store";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tag = "data-dir";
|
||||||
|
source = "/var/lib/${vm-name}";
|
||||||
|
mountPoint = "/mnt";
|
||||||
|
proto = "virtiofs";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tag = "media-dir";
|
||||||
|
source = "/media/shows";
|
||||||
|
mountPoint = "/media/shows";
|
||||||
|
proto = "virtiofs";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
# Allow the service to use the share
|
||||||
|
system.activationScripts."chownDataDir" = lib.stringAfter ["var"] ''
|
||||||
|
mkdir -p /mnt
|
||||||
|
chmod -R 770 /mnt
|
||||||
|
chown -R sonarr:sonarr /mnt
|
||||||
|
'';
|
||||||
|
systemd.services.sonarr.serviceConfig.ExecStartPre = "/run/current-system/sw/bin/sleep 5";
|
||||||
|
systemd.services.rutorrent.serviceConfig.ExecStartPre = "/run/current-system/sw/bin/sleep 5";
|
||||||
|
|
||||||
|
microvm.hypervisor = "qemu";
|
||||||
|
|
||||||
|
# VM Networking
|
||||||
|
microvm.interfaces = [
|
||||||
|
{
|
||||||
|
id = "vm${toString vm-index}";
|
||||||
|
type = "tap";
|
||||||
|
mac = vm-mac;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
networking.useNetworkd = true;
|
||||||
|
systemd.network.networks."10-eth" = {
|
||||||
|
matchConfig.MACAddress = vm-mac;
|
||||||
|
address = [
|
||||||
|
"10.0.0.${toString vm-index}/32"
|
||||||
|
];
|
||||||
|
routes = [
|
||||||
|
# Host Route
|
||||||
|
{
|
||||||
|
Destination = "10.0.0.0/32";
|
||||||
|
GatewayOnLink = true;
|
||||||
|
}
|
||||||
|
# Default route
|
||||||
|
{
|
||||||
|
Destination = "0.0.0.0/0";
|
||||||
|
Gateway = "10.0.0.0";
|
||||||
|
GatewayOnLink = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
networkConfig = {
|
||||||
|
DNS = [
|
||||||
|
"9.9.9.9"
|
||||||
|
"8.8.8.8"
|
||||||
|
"8.8.4.4"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.nameservers = [
|
||||||
|
"10.0.101.1"
|
||||||
|
"8.8.8.8"
|
||||||
|
"8.8.4.4"
|
||||||
|
];
|
||||||
|
|
||||||
|
programs.nano.enable = lib.mkForce false;
|
||||||
|
programs.vim.enable = true;
|
||||||
|
|
||||||
|
# Services
|
||||||
|
services.sonarr = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
dataDir = "/mnt/sonarr";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.rtorrent = {
|
||||||
|
enable = true;
|
||||||
|
dataDir = "/mnt/rtorrent";
|
||||||
|
user = "rtorrent";
|
||||||
|
group = "rtorrent";
|
||||||
|
port = 9999;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Debug user
|
||||||
|
users.users."root" = {
|
||||||
|
password = "1234";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = [pkgs.dig];
|
||||||
|
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
PermitRootLogin = "yes";
|
||||||
|
AllowUsers = null;
|
||||||
|
PasswordAuthentication = true;
|
||||||
|
KbdInteractiveAuthentication = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config.networking.firewall.allowedTCPPorts = [port 80 433];
|
||||||
|
config.networking.firewall.allowedUDPPorts = [port 80 433];
|
||||||
|
|
||||||
|
config.services.nginx.virtualHosts."sonarr.spoodythe.one" = {
|
||||||
|
addSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
port = 8989;
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
ssl = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
port = 443;
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://10.0.0.${toString vm-index}:${toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
25
services/sonarr.nix
Normal file
25
services/sonarr.nix
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{...}: let
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 8989;
|
||||||
|
in {
|
||||||
|
users.extraUsers.sonarr.extraGroups = ["jellyfin"]; # Access to the media folder
|
||||||
|
services.sonarr = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
};
|
||||||
|
services.rtorrent = {
|
||||||
|
enable = true;
|
||||||
|
dataDir = "/mnt/rtorrent";
|
||||||
|
user = "rtorrent";
|
||||||
|
group = "rtorrent";
|
||||||
|
port = 9999;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."sonarr.spoodythe.one" = {
|
||||||
|
addSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${host}:${toString port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,7 +2,6 @@
|
||||||
host = "127.0.0.1";
|
host = "127.0.0.1";
|
||||||
port = 8222;
|
port = 8222;
|
||||||
in {
|
in {
|
||||||
imports = [./nginx.nix];
|
|
||||||
services.vaultwarden = {
|
services.vaultwarden = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
|
@ -25,6 +24,9 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [port];
|
||||||
|
networking.firewall.allowedUDPPorts = [port];
|
||||||
|
|
||||||
services.nginx.virtualHosts."vaultwarden.spoodythe.one" = {
|
services.nginx.virtualHosts."vaultwarden.spoodythe.one" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
|
|
133
services/vm-test.nix
Normal file
133
services/vm-test.nix
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
vm-index = 1;
|
||||||
|
vm-mac = "02:00:00:00:00:02";
|
||||||
|
in {
|
||||||
|
config.microvm.vms."vm-test" = {
|
||||||
|
config = {...}: {
|
||||||
|
microvm.interfaces = [
|
||||||
|
{
|
||||||
|
id = "vm${toString vm-index}";
|
||||||
|
type = "tap";
|
||||||
|
mac = vm-mac;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
microvm.shares = [
|
||||||
|
{
|
||||||
|
tag = "ro-store";
|
||||||
|
source = "/nix/store";
|
||||||
|
mountPoint = "/nix/.ro-store";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.useNetworkd = true;
|
||||||
|
networking.usePredictableInterfaceNames = false;
|
||||||
|
systemd.network.networks."10-eth" = {
|
||||||
|
matchConfig.MACAddress = vm-mac;
|
||||||
|
address = [
|
||||||
|
"10.0.0.${toString vm-index}/32"
|
||||||
|
];
|
||||||
|
routes = [
|
||||||
|
# Host Route
|
||||||
|
{
|
||||||
|
Destination = "10.0.0.0/32";
|
||||||
|
GatewayOnLink = true;
|
||||||
|
}
|
||||||
|
# Default route
|
||||||
|
{
|
||||||
|
Destination = "0.0.0.0/0";
|
||||||
|
Gateway = "10.0.0.0";
|
||||||
|
GatewayOnLink = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
networkConfig = {
|
||||||
|
DNS = [
|
||||||
|
"9.9.9.9"
|
||||||
|
"8.8.8.8"
|
||||||
|
"8.8.4.4"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.nameservers = [
|
||||||
|
"10.0.101.1"
|
||||||
|
"8.8.8.8"
|
||||||
|
"8.8.4.4"
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services."wireguard-kill-switch" = {
|
||||||
|
description = "Wireguard Kill Switch";
|
||||||
|
after = ["network-online.target"];
|
||||||
|
wants = ["network-online.target"];
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
type = "oneshot";
|
||||||
|
ExecStart = pkgs.writeShellScript "wgconf.sh" ''
|
||||||
|
# Stay a while and listen
|
||||||
|
# ${pkgs.toybox}/bin/sleep 5
|
||||||
|
# Route local traffic through wg0 except local traffic
|
||||||
|
${pkgs.iproute2}/bin/ip route add 10.0.0.0/32 dev eth0 && \
|
||||||
|
${pkgs.iproute2}/bin/ip route add 0.0.0.0/1 dev wg0
|
||||||
|
# Block all traffic that isnt local or through the vpn
|
||||||
|
${pkgs.iptables}/bin/iptables -I OUTPUT ! -o wg0 -m mark ! --mark 42 -m addrtype ! --dst-type LOCAL ! -d 10.0.0.0/32 -j REJECT
|
||||||
|
'';
|
||||||
|
RemainAfterExit = "yes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.wireguard.enable = true;
|
||||||
|
systemd.network = {
|
||||||
|
netdevs."10-wg0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = "wireguard";
|
||||||
|
Name = "wg0";
|
||||||
|
MTUBytes = "1300";
|
||||||
|
};
|
||||||
|
wireguardConfig = {
|
||||||
|
PrivateKeyFile = "${./wireguard-secret}";
|
||||||
|
FirewallMark = 42;
|
||||||
|
ListenPort = 51820;
|
||||||
|
};
|
||||||
|
wireguardPeers = [
|
||||||
|
{
|
||||||
|
PublicKey = "0qSP0VxoIhEhRK+fAHVvmfRdjPs2DmmpOCNLFP/7cGw=";
|
||||||
|
AllowedIPs = ["0.0.0.0/0"];
|
||||||
|
Endpoint = "193.32.248.66:51820";
|
||||||
|
# PersistentKeepalive = 25;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
networks."wg0" = {
|
||||||
|
matchConfig.Name = "wg0";
|
||||||
|
address = [
|
||||||
|
" 10.65.241.123/32"
|
||||||
|
];
|
||||||
|
DHCP = "no";
|
||||||
|
dns = ["10.64.0.1"];
|
||||||
|
gateway = [
|
||||||
|
"10.0.0.0"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.root = {
|
||||||
|
password = "1234";
|
||||||
|
};
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
PermitRootLogin = "yes";
|
||||||
|
AllowUsers = null;
|
||||||
|
PasswordAuthentication = true;
|
||||||
|
KbdInteractiveAuthentication = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
4
services/vpn.nix
Normal file
4
services/vpn.nix
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{pkgs, ...}: {
|
||||||
|
services.mullvad-vpn.enable = true;
|
||||||
|
environment.systemPackages = [pkgs.wireguard-tools];
|
||||||
|
}
|
|
@ -5,77 +5,12 @@
|
||||||
}: let
|
}: let
|
||||||
host = "127.0.0.1";
|
host = "127.0.0.1";
|
||||||
port = 8080;
|
port = 8080;
|
||||||
user = "website-host-user";
|
|
||||||
repo = "https://git.spoodythe.one/spoody/website";
|
|
||||||
in {
|
in {
|
||||||
imports = [./nginx.nix];
|
|
||||||
services.nginx.virtualHosts."spoodythe.one" = {
|
services.nginx.virtualHosts."spoodythe.one" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
default = true;
|
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://${host}:${toString port}";
|
proxyPass = "http://${host}:${toString port}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users."${user}" = {
|
|
||||||
isSystemUser = true;
|
|
||||||
home = "/home/${user}";
|
|
||||||
createHome = true;
|
|
||||||
group = "${user}";
|
|
||||||
shell = pkgs.bash;
|
|
||||||
openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG90JNokb4/4DZ/2tHS8Lj/jq+UiA0B2g+MFeM8KuA6Y website-host-user@server"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
users.groups."${user}" = {};
|
|
||||||
|
|
||||||
security.sudo.extraRules = [
|
|
||||||
{
|
|
||||||
users = ["${user}"];
|
|
||||||
commands = [
|
|
||||||
{
|
|
||||||
command = "/run/current-system/sw/bin/systemctl restart rebuild-website.service";
|
|
||||||
options = ["SETENV" "NOPASSWD"];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
command = "/run/current-system/sw/bin/systemd-run -d --uid website-host-user ./webbisitey";
|
|
||||||
options = ["SETENV" "NOPASSWD"];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services."rebuild-website" = {
|
|
||||||
description = "Service for running my website";
|
|
||||||
wants = ["network-online.target"];
|
|
||||||
after = ["network-online.target"];
|
|
||||||
wantedBy = ["multi-user.target"];
|
|
||||||
|
|
||||||
script = ''
|
|
||||||
echo "Sleeping for 25 seconds to allow forgejo to start"
|
|
||||||
${pkgs.busybox}/bin/sleep 25
|
|
||||||
echo "Making temporary folder"
|
|
||||||
path=$(mktemp -d)
|
|
||||||
echo "Cloning repo"
|
|
||||||
${pkgs.git}/bin/git clone ${repo} "$path"
|
|
||||||
echo "cd $path"
|
|
||||||
cd "$path"
|
|
||||||
echo "[nix build] Rebuilding website flake..."
|
|
||||||
${pkgs.nix}/bin/nix build # build
|
|
||||||
echo "[killall] Killing previous website process"
|
|
||||||
${pkgs.killall}/bin/killall webbisitey || true # stop old website
|
|
||||||
echo "Changing directory to build result..."
|
|
||||||
cd result/bin # cd into result folder
|
|
||||||
echo "[systemd-run] Running webbisitey-wrapped..."
|
|
||||||
/run/wrappers/bin/sudo /run/current-system/sw/bin/systemd-run -d --uid ${user} ./webbisitey # run new website
|
|
||||||
'';
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainsAfterExit = true;
|
|
||||||
User = user;
|
|
||||||
WorkingDirectory = "/tmp";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{pkgs, ...}: {
|
{...}: {
|
||||||
services.zfs.zed = {
|
services.zfs.zed = {
|
||||||
enableMail = true;
|
enableMail = true;
|
||||||
settings = {
|
settings = {
|
||||||
ZED_DEBUG_LOG = "/tmp/zed.debug.log";
|
ZED_DEBUG_LOG = "/tmp/zed.debug.log";
|
||||||
ZED_EMAIL_ADDR = "snorre@altschul.dk";
|
ZED_EMAIL_ADDR = "snorre@altschul.dk";
|
||||||
ZED_EMAIL_PROG = "${pkgs.postfix}/bin/sendmail";
|
ZED_EMAIL_PROG = "sendmail";
|
||||||
ZED_EMAIL_OPTS = " @ADDRESS@";
|
ZED_EMAIL_OPTS = "-s '@SUBJECT@' @ADDRESS@";
|
||||||
|
|
||||||
ZED_LOCKDIR = "/var/lock";
|
ZED_LOCKDIR = "/var/lock";
|
||||||
ZED_NOTIFY_INTERVAL_SECS = 3600;
|
ZED_NOTIFY_INTERVAL_SECS = 3600;
|
||||||
|
|
Loading…
Reference in a new issue