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/openssh.nix
|
||||
./services/forgejo.nix
|
||||
# ./services/nextcloud.nix
|
||||
# ./services/seafile.nix
|
||||
./services/vaultwarden.nix
|
||||
./services/jellyfin.nix
|
||||
./services/website.nix
|
||||
./services/mailserver.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/git.nix
|
||||
./modules/nix-settings.nix
|
||||
./modules/zfs.nix
|
||||
./modules/microvm.nix
|
||||
|
||||
(import ./modules/microvm.nix {routed = true;})
|
||||
(import ./modules/networking-shared.nix {hostname = "server";})
|
||||
(import ./modules/users.nix {main-user = "baritone";})
|
||||
];
|
||||
|
@ -39,11 +42,21 @@
|
|||
# Enable microcode updates
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
|
||||
# programs.zsh = {
|
||||
# enable = true;
|
||||
# enableGlobalCompInit = true;
|
||||
# shellAliases = {
|
||||
# "nrb" = "sudo nixos-rebuild switch --flake /etc/nixos";
|
||||
# };
|
||||
# };
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
wget
|
||||
curl
|
||||
git
|
||||
vim
|
||||
|
||||
inputs.agenix.packages."${system}".default
|
||||
];
|
||||
|
||||
programs.nano.enable = false;
|
||||
|
|
28
disko.nix
28
disko.nix
|
@ -8,14 +8,12 @@
|
|||
disko.devices = {
|
||||
disk =
|
||||
{
|
||||
# Main SSD where /nix/store /etc /boot etc. is located.
|
||||
main = {
|
||||
type = "disk";
|
||||
device = root-disk;
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
# Define a 512 megabyte boot partition
|
||||
boot = {
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
|
@ -26,7 +24,6 @@
|
|||
mountOptions = ["umask=0077"];
|
||||
};
|
||||
};
|
||||
# If the swap argument is defined then create a swap partition of the given size
|
||||
swap = lib.mkIf (swap-size != -1) {
|
||||
size = swap-size;
|
||||
content = {
|
||||
|
@ -35,7 +32,6 @@
|
|||
resumeDevice = true;
|
||||
};
|
||||
};
|
||||
# Finally allocate the rest of the disk as a zfs device
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
|
@ -66,13 +62,12 @@
|
|||
});
|
||||
|
||||
zpool = {
|
||||
# Set up zroot pool
|
||||
zroot = {
|
||||
type = "zpool";
|
||||
rootFsOptions = {
|
||||
mountpoint = "none";
|
||||
acltype = "posixacl"; # POSIX compliant file permissions
|
||||
xattr = "sa"; # Store attributes in inodes to reduce disk reads
|
||||
acltype = "posixacl";
|
||||
xattr = "sa";
|
||||
};
|
||||
|
||||
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) {
|
||||
type = "zpool";
|
||||
mode = "raidz";
|
||||
|
||||
rootFsOptions = {
|
||||
compression = "zstd"; # Compress filesystem for more storage
|
||||
mountpoint = "none"; # Dont mount the zfs pool anywhere
|
||||
acltype = "posixacl"; # POSIX compliant file permissions
|
||||
xattr = "sa"; # Store attributes in inodes to reduce disk reads
|
||||
"com.sun:auto-snapshot" = "true"; # Never a bad idea to have backups
|
||||
compression = "zstd";
|
||||
mountpoint = "none";
|
||||
acltype = "posixacl";
|
||||
xattr = "sa";
|
||||
"com.sun:auto-snapshot" = "true";
|
||||
};
|
||||
|
||||
datasets = {
|
||||
|
@ -118,10 +112,10 @@
|
|||
type = "zfs_fs";
|
||||
mountpoint = "/opt";
|
||||
};
|
||||
# media = {
|
||||
# type = "zfs_fs";
|
||||
# mountpoint = "/media";
|
||||
# };
|
||||
media = {
|
||||
type = "zfs_fs";
|
||||
mountpoint = "/media";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
18
flake.lock
18
flake.lock
|
@ -143,11 +143,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743295846,
|
||||
"narHash": "sha256-hKKz07d4RV9gzxzE5Qu3RQWX8a7XpzRrP5timoxoGRQ=",
|
||||
"lastModified": 1742326330,
|
||||
"narHash": "sha256-Tumt3tcMXJniSh7tw2gW+WAnVLeB3WWm+E+yYFnLBXo=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "717030011980e9eb31eb8ce011261dd532bce92c",
|
||||
"rev": "22a36aa709de7dd42b562a433b9cefecf104a6ee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -165,11 +165,11 @@
|
|||
"spectrum": "spectrum"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743083165,
|
||||
"narHash": "sha256-Fz7AiCJWtoWZ2guJwO3B1h3RuJxYWaCzFIqY0Kmkyrs=",
|
||||
"lastModified": 1741893540,
|
||||
"narHash": "sha256-NEsR+FQ+AsY4cOZ3OL69JVdPTAYzSzBqeAhHGRRuDGk=",
|
||||
"owner": "astro",
|
||||
"repo": "microvm.nix",
|
||||
"rev": "773d5a04e2e10ca7b412270dea11276a496e1b61",
|
||||
"rev": "5bbc126db87b5ffc36394df630eead403c48fac8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -180,11 +180,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1743095683,
|
||||
"narHash": "sha256-gWd4urRoLRe8GLVC/3rYRae1h+xfQzt09xOfb0PaHSk=",
|
||||
"lastModified": 1742288794,
|
||||
"narHash": "sha256-Txwa5uO+qpQXrNG4eumPSD+hHzzYi/CdaM80M9XRLCo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5e5402ecbcb27af32284d4a62553c019a3a49ea6",
|
||||
"rev": "b6eaf97c6960d97350c584de1b6dcff03c9daf42",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -1,15 +1,4 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
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];
|
||||
{config, ...}: {
|
||||
# This is where the age files go
|
||||
# age.secrets.nextcloud.file = ../secrets/nextcloud.age;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{routed ? false}: {
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
|
|
|
@ -34,8 +34,5 @@
|
|||
"nrb" = "sudo nixos-rebuild switch --flake /etc/nixos";
|
||||
"vmr" = "rm ~/.ssh/known_hosts; ssh root@10.0.0.1";
|
||||
};
|
||||
shellAliases = {
|
||||
"fucking" = "sudo";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,4 +8,8 @@
|
|||
environment.systemPackages = with pkgs; [
|
||||
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"];
|
||||
in {
|
||||
"nextcloud.age".publicKeys = public-keys;
|
||||
"forgejo-runner-token.age".publicKeys = public-keys;
|
||||
}
|
||||
|
|
|
@ -5,28 +5,14 @@
|
|||
}: let
|
||||
lib = pkgs.lib;
|
||||
host = "10.0.${toString vm-index}.1";
|
||||
|
||||
ports = {
|
||||
sonarr.port = 8989;
|
||||
radarr.port = 7878;
|
||||
jackett.port = 9117;
|
||||
};
|
||||
|
||||
port = 8989;
|
||||
vm-index = 1;
|
||||
vm-mac = "02:00:00:00:00:02";
|
||||
vm-name = "auto-torrent";
|
||||
vpn-endpoint = "193.32.248.70";
|
||||
enable-services = true;
|
||||
wg-config = "/mnt/wg.conf";
|
||||
jellyfin-gid = 989;
|
||||
|
||||
ports-list = (pkgs.lib.attrsets.mapAttrsToList (name: value: value.port) ports) ++ [9091];
|
||||
in {
|
||||
microvm.autostart = [vm-name];
|
||||
imports = [
|
||||
./nginx.nix
|
||||
../modules/microvm.nix
|
||||
];
|
||||
|
||||
users.extraUsers.microvm.extraGroups = [
|
||||
"jellyfin" # access to media folder
|
||||
|
@ -34,7 +20,9 @@ in {
|
|||
|
||||
system.activationScripts."make-${vm-name}-data-dir" = lib.stringAfter ["var"] ''
|
||||
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} = {
|
||||
|
@ -48,8 +36,6 @@ in {
|
|||
}
|
||||
];
|
||||
|
||||
time.timeZone = "Europe/Copenhagen";
|
||||
|
||||
# 1gb of memory
|
||||
microvm.mem = 1024;
|
||||
|
||||
|
@ -69,7 +55,7 @@ in {
|
|||
}
|
||||
{
|
||||
tag = "media-dir";
|
||||
source = "/var/lib/media";
|
||||
source = "/media";
|
||||
mountPoint = "/media";
|
||||
inherit proto;
|
||||
}
|
||||
|
@ -115,7 +101,7 @@ in {
|
|||
serviceConfig = {
|
||||
type = "oneshot";
|
||||
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";
|
||||
};
|
||||
|
@ -133,18 +119,6 @@ in {
|
|||
programs.nano.enable = lib.mkForce false;
|
||||
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.sonarr = pkgs.lib.mkIf enable-services {
|
||||
enable = true;
|
||||
|
@ -164,25 +138,11 @@ in {
|
|||
|
||||
services.transmission = pkgs.lib.mkIf enable-services {
|
||||
enable = true;
|
||||
openPeerPorts = true;
|
||||
openRPCPort = true;
|
||||
openFirewall = true;
|
||||
home = "/mnt/transmission";
|
||||
webHome = "${pkgs.flood-for-transmission}";
|
||||
settings = {
|
||||
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"];
|
||||
};
|
||||
settings.download-dir = "/mnt/transmission";
|
||||
settings.incomplete-dir = "/mnt/transmission/.incomplete";
|
||||
downloadDirPermissions = "775";
|
||||
performanceNetParameters = true;
|
||||
};
|
||||
|
||||
# debugging
|
||||
|
@ -209,16 +169,13 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
# Add virtual hosts for all the different services running in the vm
|
||||
services.nginx.virtualHosts = builtins.listToAttrs (pkgs.lib.attrsets.mapAttrsToList (
|
||||
name: value: {
|
||||
name = "${name}.spoodythe.one";
|
||||
value = {
|
||||
# Sonarr
|
||||
services.nginx.virtualHosts."sonarr.spoodythe.one" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
listen = [
|
||||
{
|
||||
port = value.port;
|
||||
inherit port;
|
||||
addr = "0.0.0.0";
|
||||
ssl = false;
|
||||
}
|
||||
|
@ -229,21 +186,56 @@ in {
|
|||
}
|
||||
];
|
||||
locations."/" = {
|
||||
proxyPass = "http://${host}:${toString value.port}";
|
||||
proxyPass = "http://${host}:${toString port}";
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
ports);
|
||||
|
||||
# Forward transmission web port to vm
|
||||
networking.nat.forwardPorts = [
|
||||
# Radarr
|
||||
services.nginx.virtualHosts."radarr.spoodythe.one" = let
|
||||
port = 7878;
|
||||
in {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
listen = [
|
||||
{
|
||||
sourcePort = 9091;
|
||||
destination = "${host}:9091";
|
||||
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;
|
||||
networking.firewall.allowedUDPPorts = ports-list;
|
||||
# Jackett
|
||||
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,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
jails = {
|
||||
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 {
|
||||
}: {
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
|
||||
bantime = "24h";
|
||||
|
@ -41,8 +15,7 @@ in {
|
|||
overalljails = true;
|
||||
};
|
||||
|
||||
jails =
|
||||
{
|
||||
jails = {
|
||||
dovecot = lib.mkIf config.services.dovecot2.enable {
|
||||
settings = {
|
||||
# block IPs which failed to log-in
|
||||
|
@ -51,24 +24,31 @@ in {
|
|||
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 ''
|
||||
[Definition]
|
||||
failregex = ^.*Authentication request for .* has been denied \(IP: <ADDR>\)\.
|
||||
'');
|
||||
# Defines a filter that detects URL probing by reading the Nginx access log
|
||||
"fail2ban/filter.d/nginx-url-probe.local".text = lib.mkDefault (lib.mkAfter ''
|
||||
"fail2ban/filter.d/nginx-url-probe.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
|
||||
[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})
|
||||
'');
|
||||
}
|
||||
// (with lib.attrsets;
|
||||
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";
|
||||
port = 6969;
|
||||
in {
|
||||
imports = [
|
||||
./nginx.nix
|
||||
./gitea-actions-runner.nix
|
||||
];
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
|
||||
|
@ -17,10 +13,6 @@ in {
|
|||
APP_NAME = "An idiot admires complexity. A genius admires simplicity";
|
||||
};
|
||||
|
||||
repository = {
|
||||
ENABLE_PUSH_CREATE_USER = true;
|
||||
};
|
||||
|
||||
server = {
|
||||
DOMAIN = "git.spoodythe.one";
|
||||
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
|
||||
host = "127.0.0.1";
|
||||
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 {
|
||||
imports = [./nginx.nix];
|
||||
# Enable VAAPI
|
||||
config.nixpkgs.config.packageOverrides = pkgs: {
|
||||
vaapiIntel = pkgs.vaapiIntel.override {enableHybridCodec = true;};
|
||||
|
@ -24,19 +50,17 @@ in {
|
|||
];
|
||||
};
|
||||
|
||||
# Set declarative gid
|
||||
config.users.groups.jellyfin.gid = gid;
|
||||
|
||||
# Create folder for media
|
||||
config.system.activationScripts."jellyfinMediaFolder" = lib.stringAfter ["var"] ''
|
||||
mkdir -p /var/lib/media
|
||||
chmod 770 /var/lib/media
|
||||
chown -R jellyfin:jellyfin /var/lib/media
|
||||
mkdir -p /media
|
||||
chmod -R 775 /media
|
||||
chown -R jellyfin:jellyfin /media
|
||||
'';
|
||||
|
||||
# Enable Jellyfin
|
||||
config.services.jellyfin = {
|
||||
enable = true;
|
||||
package = jellyfin;
|
||||
openFirewall = false; # We want jellyfin behind a reverse proxy
|
||||
};
|
||||
|
||||
|
@ -54,7 +78,6 @@ in {
|
|||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://${host}:${toString port}";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
# Websocket support
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
|
@ -66,7 +89,7 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
# Open ports for local network access
|
||||
config.networking.firewall.allowedTCPPorts = [port];
|
||||
config.networking.firewall.allowedUDPPorts = [port];
|
||||
# Open port 80 and 443 for reverse proxy
|
||||
config.networking.firewall.allowedTCPPorts = [port 80 443];
|
||||
config.networking.firewall.allowedUDPPorts = [port 80 443];
|
||||
}
|
||||
|
|
|
@ -5,12 +5,17 @@
|
|||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
|
||||
virtualHosts."spoodythe.one" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
default = true;
|
||||
locations."/" = {
|
||||
return = 404;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
security.acme.acceptTerms = true;
|
||||
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";
|
||||
port = 8222;
|
||||
in {
|
||||
imports = [./nginx.nix];
|
||||
services.vaultwarden = {
|
||||
enable = true;
|
||||
|
||||
|
@ -25,6 +24,9 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [port];
|
||||
networking.firewall.allowedUDPPorts = [port];
|
||||
|
||||
services.nginx.virtualHosts."vaultwarden.spoodythe.one" = {
|
||||
enableACME = 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
|
||||
host = "127.0.0.1";
|
||||
port = 8080;
|
||||
user = "website-host-user";
|
||||
repo = "https://git.spoodythe.one/spoody/website";
|
||||
in {
|
||||
imports = [./nginx.nix];
|
||||
services.nginx.virtualHosts."spoodythe.one" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
default = true;
|
||||
locations."/" = {
|
||||
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 = {
|
||||
enableMail = true;
|
||||
settings = {
|
||||
ZED_DEBUG_LOG = "/tmp/zed.debug.log";
|
||||
ZED_EMAIL_ADDR = "snorre@altschul.dk";
|
||||
ZED_EMAIL_PROG = "${pkgs.postfix}/bin/sendmail";
|
||||
ZED_EMAIL_OPTS = " @ADDRESS@";
|
||||
ZED_EMAIL_PROG = "sendmail";
|
||||
ZED_EMAIL_OPTS = "-s '@SUBJECT@' @ADDRESS@";
|
||||
|
||||
ZED_LOCKDIR = "/var/lock";
|
||||
ZED_NOTIFY_INTERVAL_SECS = 3600;
|
||||
|
|
Loading…
Reference in a new issue