refactor: config/hosts => hosts

This commit is contained in:
2025-12-27 17:58:48 +08:00
parent 99aea69128
commit f9308dda9e
40 changed files with 4 additions and 21 deletions

View File

@@ -0,0 +1,42 @@
{
lib,
config,
pkgs,
secrets,
hosts,
...
}:
{
sops.secrets.et-imxyy-nix-server-nixremote = {
sopsFile = secrets.et-imxyy-nix-server-nixremote;
restartUnits = [ "easytier-nixremote.service" ];
format = "binary";
};
environment.systemPackages = [ pkgs.easytier ];
systemd.services."easytier-nixremote" = {
enable = true;
script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix-server-nixremote.path}";
serviceConfig = {
Restart = "always";
RestartSec = 30;
User = "root";
};
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"sops-nix.service"
];
};
users.groups.nixremote = { };
users.users.nixremote = {
isSystemUser = true;
description = "nix remote build user";
group = "nixremote";
openssh.authorizedKeys.keys = (lib.mapAttrsToList (host: key: "${key} ${host}") hosts) ++ [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIENauvvhVMLsUwH9cPYsvnOg7VCL3a4yEiKm8I524TE efl@efl-nix"
];
};
nix.settings.trusted-users = [
"nixremote"
];
}

View File

@@ -0,0 +1,10 @@
{
services.caddy = {
enable = true;
email = "acme@imxyy.top";
};
security.acme = {
acceptTerms = true;
defaults.email = "acme@imxyy.top";
};
}

View File

@@ -0,0 +1,15 @@
{
services.coder = {
enable = true;
accessUrl = "https://coder.imxyy.top";
listenAddress = "127.0.0.1:8086";
};
users.users.coder.extraGroups = [ "podman" ];
services.caddy.virtualHosts."coder.imxyy.top" = {
extraConfig = ''
reverse_proxy :8086 {
header_up X-Real-IP {remote_host}
}
'';
};
}

View File

@@ -0,0 +1,14 @@
{ lib, ... }:
{
virtualisation.oci-containers.backend = lib.mkForce "podman";
virtualisation.podman = {
enable = true;
dockerCompat = true;
dockerSocket.enable = true;
defaultNetwork.settings.dns_enabled = true;
};
# avoid collision with dnsmasq
virtualisation.containers = {
containersConf.settings.network.dns_bind_port = 5353;
};
}

View File

@@ -0,0 +1,55 @@
{ config, secrets, ... }:
{
sops.secrets.efl-tuwunel-env = {
sopsFile = secrets.efl-tuwunel;
restartUnits = [ "podman-tuwunel.service" ];
format = "dotenv";
};
virtualisation.oci-containers.containers = {
tuwunel = {
image = "jevolk/tuwunel:latest";
volumes = [
"tuwunel_db:/var/lib/tuwunel"
];
ports = [ "6167:6167" ];
networks = [ "podman" ];
environment = {
TUWUNEL_SERVER_NAME = "mtx.eflx.top";
TUWUNEL_PORT = "6167";
TUWUNEL_ADDRESS = "0.0.0.0";
TUWUNEL_WELL_KNOWN__SERVER = "mtx.eflx.top:443";
TUWUNEL_WELL_KNOWN__CLIENT = "https://mtx.eflx.top";
};
environmentFiles = [
config.sops.secrets.efl-tuwunel-env.path
];
};
mautrix-telegram = {
image = "dock.mau.dev/mautrix/telegram:latest";
ports = [ "8099:8099" ];
networks = [ "podman" ];
extraOptions = [ "--ip=10.88.0.254" ];
volumes = [ "/var/lib/efl-mautrix-telegram:/data" ];
};
send = {
image = "lanol/filecodebox:latest";
ports = [ "12345:12345" ];
volumes = [ "/var/lib/send:/app/data:rw" ];
};
};
services.caddy.virtualHosts."mtx.eflx.top" = {
extraConfig = ''
reverse_proxy :6167 {
header_up X-Real-IP {remote_host}
}
'';
};
services.caddy.virtualHosts."send.eflx.top" = {
extraConfig = ''
reverse_proxy :12345 {
header_up X-Real-IP {remote_host}
}
'';
};
}

View File

@@ -0,0 +1,45 @@
{
services.caddy.virtualHosts."git.imxyy.top" = {
extraConfig = ''
reverse_proxy :8082 {
header_up X-Real-IP {remote_host}
}
'';
};
services.gitea = {
enable = true;
appName = "imxyy_soope_'s Gitea";
user = "git";
group = "git";
mailerPasswordFile = "/var/lib/gitea/smtp_password";
stateDir = "/mnt/nas/gitea";
settings = {
globalSection = {
LANDING_PAGE = "explore";
};
server = {
DOMAIN = "git.imxyy.top";
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 8082;
ROOT_URL = "https://git.imxyy.top/";
SSH_PORT = 2222;
};
service = {
REGISTER_MANUAL_CONFIRM = true;
};
};
};
services.openssh.ports = [
22
2222
];
users = {
users.git = {
isNormalUser = true;
description = "git user";
group = "git";
home = "/mnt/nas/gitea";
};
groups.git = { };
};
}

View File

@@ -0,0 +1,43 @@
{
services.grafana = {
enable = true;
settings = {
server = {
http_addr = "0.0.0.0";
http_port = 8090;
domain = "grafana.imxyy.top";
};
};
};
services.prometheus = {
enable = true;
port = 8091;
exporters = {
node = {
enable = true;
port = 8092;
enabledCollectors = [
"systemd"
"zfs"
];
};
};
scrapeConfigs = [
{
job_name = "node";
static_configs = [
{
targets = [ "127.0.0.1:8092" ];
}
];
}
];
};
services.caddy.virtualHosts."grafana.imxyy.top" = {
extraConfig = ''
reverse_proxy :8090 {
header_up X-Real-IP {remote_host}
}
'';
};
}

View File

@@ -0,0 +1,112 @@
{
config,
lib,
pkgs,
...
}:
let
btrfs = "/dev/disk/by-uuid/c7889c5c-c5b6-4e3c-9645-dfd49c2e84d0";
in
{
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ "amdgpu" ];
boot.kernelModules = [ "kvm-amd" ];
boot.kernelPackages = lib.mkForce pkgs.linuxPackages_xanmod_latest;
services.scx = {
enable = true;
scheduler = "scx_rusty";
};
boot.extraModulePackages = [ ];
boot.tmp.useTmpfs = true;
boot.supportedFilesystems = [ "zfs" ];
boot.zfs = {
extraPools = [ "data" ];
forceImportRoot = false;
};
services.zfs.autoScrub.enable = true;
services.btrfs.autoScrub.enable = true;
networking.hostId = "10ca95b4";
fileSystems."/" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=root"
];
};
fileSystems."/nix" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=nix"
];
};
my.persist.location = "/nix/persist";
fileSystems."/nix/persist" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=persist"
];
neededForBoot = true;
};
boot.initrd.postDeviceCommands = lib.mkAfter ''
mkdir /btrfs_tmp
mount ${btrfs} /btrfs_tmp
mkdir -p /btrfs_tmp/old_roots
if [[ -e /btrfs_tmp/root ]]; then
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +14); do
delete_subvolume_recursively "$i"
done
btrfs subvolume create /btrfs_tmp/root
umount /btrfs_tmp
'';
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/32AA-2998";
fsType = "vfat";
options = [
"uid=0"
"gid=0"
"fmask=0077"
"dmask=0077"
];
};
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault false;
hardware.enableRedistributableFirmware = lib.mkDefault true;
hardware.cpu.amd.updateMicrocode = config.hardware.enableRedistributableFirmware;
nixpkgs.hostPlatform = lib.mkForce "x86_64-linux";
}

View File

@@ -0,0 +1,25 @@
{ lib, ... }:
{
my = {
cli.all.enable = true;
cli.media.all.enable = lib.mkForce false;
coding.editor.neovim.enable = true;
coding.misc.enable = true;
coding.langs.lua.enable = true;
coding.langs.rust.enable = true;
coding.langs.js.enable = true;
fonts.enable = lib.mkForce false;
persist = {
enable = true;
homeDirs = [
"workspace"
"Virt"
".local/state"
".cache"
".ollama"
];
};
};
}

View File

@@ -0,0 +1,14 @@
{
virtualisation.oci-containers.containers.sun-panel = {
image = "hslr/sun-panel:latest";
volumes = [
"/var/lib/sun-panel:/app/conf"
];
ports = [ "8085:3002" ];
};
services.caddy.virtualHosts."home.imxyy.top" = {
extraConfig = ''
reverse_proxy :8085
'';
};
}

View File

@@ -0,0 +1,21 @@
{ ... }:
{
users.users.immich = {
home = "/mnt/nas/immich";
createHome = true;
};
services.immich = {
enable = true;
host = "127.0.0.1";
port = 8096;
mediaLocation = "/mnt/nas/immich";
group = "nextcloud";
};
services.caddy.virtualHosts."immich.imxyy.top" = {
extraConfig = ''
reverse_proxy :8096 {
header_up X-Real-IP {remote_host}
}
'';
};
}

View File

@@ -0,0 +1,54 @@
{ pkgs, ... }:
{
services.roundcube = {
enable = true;
hostName = "mail.imxyy.top";
plugins = [
"contextmenu"
"persistent_login"
];
package = pkgs.roundcube.withPlugins (
plugins: with plugins; [
contextmenu
persistent_login
]
);
extraConfig = ''
# starttls needed for authentication, so the fqdn required to match
# the certificate
$config['imap_conn_options'] = [
'ssl' => [
'verify_peer_name' => false,
],
];
$config['imap_host'] = "tls://mail10.serv00.com";
$config['imap_user'] = "%u";
$config['imap_pass'] = "%p";
$config['smtp_conn_options'] = [
'ssl' => [
'verify_peer_name' => false,
],
];
$config['smtp_host'] = "tls://mail10.serv00.com";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
'';
};
services.nginx.virtualHosts."mail.imxyy.top" = {
listen = [
{
addr = "0.0.0.0";
port = 8087;
}
];
forceSSL = false;
enableACME = false;
};
services.caddy.virtualHosts."mail.imxyy.top" = {
extraConfig = ''
reverse_proxy :8087 {
header_up X-Real-IP {remote_host}
}
'';
};
}

View File

@@ -0,0 +1,107 @@
{
config,
secrets,
...
}:
{
nixpkgs.config.permittedInsecurePackages = [
"olm-3.2.16"
];
sops.secrets.tuwunel-reg-token = {
sopsFile = secrets.tuwunel-reg-token;
restartUnits = [ "tuwunel.service" ];
format = "binary";
owner = config.services.matrix-tuwunel.user;
group = config.services.matrix-tuwunel.group;
};
sops.secrets.tuwunel-turn-secret = {
sopsFile = secrets.tuwunel-turn-secret;
restartUnits = [ "tuwunel.service" ];
format = "binary";
owner = config.services.matrix-tuwunel.user;
group = config.services.matrix-tuwunel.group;
};
services.matrix-tuwunel = {
enable = true;
settings.global = {
address = [ "127.0.0.1" ];
port = [ 8094 ];
server_name = "imxyy.top";
well_known = {
server = "matrix.imxyy.top:443";
client = "https://matrix.imxyy.top";
};
allow_registration = true;
registration_token_file = config.sops.secrets.tuwunel-reg-token.path;
suppress_push_when_active = true;
turn_uris = [
"turn:hk.vkvm.imxyy.top?transport=udp"
"turn:hk.vkvm.imxyy.top?transport=tcp"
];
turn_secret_file = config.sops.secrets.tuwunel-turn-secret.path;
new_user_displayname_suffix = "";
};
};
services.caddy.virtualHosts."imxyy.top" = {
extraConfig = ''
handle /.well-known/matrix/server {
header Content-Type application/json
header "Access-Control-Allow-Origin" "*"
respond `{"m.server": "matrix.imxyy.top:443"}` 200
}
handle /.well-known/matrix/client {
header Content-Type application/json
header "Access-Control-Allow-Origin" "*"
respond `{"m.homeserver": {"base_url": "https://matrix.imxyy.top/"}}` 200
}
'';
};
services.caddy.virtualHosts."matrix.imxyy.top" = {
extraConfig = ''
reverse_proxy :8094
'';
};
sops.secrets.mautrix-telegram = {
sopsFile = secrets.mautrix-telegram;
restartUnits = [ "mautrix-telegram.service" ];
format = "dotenv";
owner = "mautrix-telegram";
group = "mautrix-telegram";
};
services.mautrix-telegram = {
enable = true;
environmentFile = config.sops.secrets.mautrix-telegram.path;
settings = {
homeserver = {
address = "http://127.0.0.1:8094";
domain = "imxyy.top";
};
appservice = {
address = "http://127.0.0.1:8098";
hostname = "127.0.0.1";
port = "8098";
bot_username = "telegrambot";
};
bridge = {
username_template = "telegram_{userid}";
alias_template = "telegram_{groupname}";
displayname_template = "{displayname} (Telegram)";
permissions = {
"@imxyy_soope_:imxyy.top" = "admin";
};
};
telegram = {
# borrowed from https://github.com/telegramdesktop/tdesktop/blob/9bdc19e2fd4d497c8f403891848383a88faadc25/snap/snapcraft.yaml#L134-L135
api_id = "611335";
api_hash = "d524b414d21f4d37f08684c1df41ac9c";
};
};
};
}

View File

@@ -0,0 +1,20 @@
{ lib, pkgs, ... }:
{
systemd.services."fabric1.20.6" = {
description = "fabric 1.20.6 minecraft server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
WorkingDirectory = "/opt/minecraft/fabric1.20.6";
ExecStart = "${lib.getExe' pkgs.openjdk21 "java"} -Xms1G -Xmx5G -jar fabric-server-mc.1.20.6-loader.0.15.11-launcher.1.0.1.jar";
Restart = "always";
RestartSec = 120;
};
};
my.persist = {
nixosDirs = [
"/opt/minecraft"
];
};
}

View File

@@ -0,0 +1,20 @@
{ config, secrets, ... }:
{
sops.secrets.minio-env = {
sopsFile = secrets.minio;
restartUnits = [ "minio.service" ];
format = "dotenv";
};
services.minio = {
enable = true;
listenAddress = ":9000";
consoleAddress = ":9001";
region = "cn-south-gz";
configDir = "/mnt/nas/minio/config";
dataDir = [
"/mnt/nas/minio/data"
];
rootCredentialsFile = config.sops.secrets.minio-env.path;
};
}

View File

@@ -0,0 +1,527 @@
{
config,
lib,
pkgs,
username,
hosts,
secrets,
...
}:
{
boot.kernelParams = [
"biosdevname=0"
"net.ifnames=0"
];
networking = {
useDHCP = lib.mkForce false;
dhcpcd = {
wait = "background";
IPv6rs = true;
extraConfig = ''
interface mac0
noipv4
'';
};
interfaces = {
eth0.wakeOnLan.enable = true;
eth1.wakeOnLan.enable = true;
mac0 = {
useDHCP = true;
ipv4.addresses = [
{
address = "192.168.3.2";
prefixLength = 24;
}
];
};
};
macvlans."mac0" = {
interface = "eth0";
mode = "bridge";
};
defaultGateway = {
address = "192.168.3.1";
interface = "mac0";
};
nameservers = [
"192.168.3.2"
];
firewall.enable = false;
nftables = {
enable = true;
flushRuleset = true;
ruleset = ''
table inet firewall {
set LANv4 {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
}
set LANv6 {
type ipv6_addr
flags interval
elements = { fd00::/8, fe80::/10 }
}
set tcp_ports {
type inet_service
flags interval
elements = {
http,
https,
2222,
25565
}
}
chain prerouting {
type filter hook prerouting priority mangle; policy accept;
ip daddr @LANv4 accept
ip6 daddr @LANv6 accept
}
chain output {
type filter hook output priority 100; policy accept;
ip daddr @LANv4 accept
ip6 daddr @LANv6 accept
}
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state invalid drop
ct state established,related accept
ip protocol { icmp, igmp } accept
ip saddr @LANv4 accept
ip6 saddr @LANv6 accept
tcp dport 2222 ct state new limit rate 15/minute counter accept
tcp dport @tcp_ports counter accept
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain nat {
type nat hook postrouting priority 0; policy accept;
ip saddr 192.168.3.0/24 masquerade
}
}
'';
};
};
services.openssh = {
enable = true;
settings = {
# PermitRootLogin = "yes";
PermitRootLogin = "prohibit-password";
PasswordAuthentication = true;
};
};
users.users.root.openssh.authorizedKeys.keys = lib.mapAttrsToList (
host: key: "${key} ${host}"
) hosts;
users.users.${username}.openssh.authorizedKeys.keys = lib.mapAttrsToList (
host: key: "${key} ${host}"
) hosts;
sops.secrets.dae-imxyy-nix-server = {
sopsFile = secrets.dae-imxyy-nix-server;
restartUnits = [ "dae.service" ];
format = "binary";
};
services.dae = {
enable = true;
configFile = config.sops.secrets.dae-imxyy-nix-server.path;
};
systemd.services.dae = {
after = [ "sops-nix.service" ];
serviceConfig.MemoryMax = "1G";
};
sops.secrets.mihomo = {
sopsFile = secrets.mihomo;
restartUnits = [ "mihomo.service" ];
format = "yaml";
key = "";
};
systemd.services.mihomo.after = [ "sops-nix.service" ];
services.mihomo = {
enable = true;
configFile = config.sops.secrets.mihomo.path;
webui = pkgs.metacubexd;
};
sops.secrets.frp-env = {
sopsFile = secrets.frp;
restartUnits = [ "frp.service" ];
format = "dotenv";
};
systemd.services.frp.serviceConfig.EnvironmentFile = [
config.sops.secrets.frp-env.path
];
services.frp = {
instances."" = {
enable = true;
role = "client";
settings = {
serverAddr = "{{ .Envs.FRP_SERVER_ADDR }}";
serverPort = 7000;
auth.token = "{{ .Envs.FRP_AUTH_TOKEN }}";
proxies = [
{
name = "nextcloud-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "nextcloud.imxyy.top" ];
}
{
name = "nextcloud-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "nextcloud.imxyy.top" ];
}
{
name = "oidc-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "oidc.imxyy.top" ];
}
{
name = "oidc-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "oidc.imxyy.top" ];
}
{
name = "mail-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "mail.imxyy.top" ];
}
{
name = "mail-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "mail.imxyy.top" ];
}
{
name = "gitea-ssh";
type = "tcp";
localIP = "127.0.0.1";
localPort = 2222;
remotePort = 2222;
}
{
name = "gitea-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "git.imxyy.top" ];
}
{
name = "gitea-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "git.imxyy.top" ];
}
{
name = "vault-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "vault.imxyy.top" ];
}
{
name = "vault-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "vault.imxyy.top" ];
}
{
name = "home-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "home.imxyy.top" ];
}
{
name = "home-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "home.imxyy.top" ];
}
{
name = "coder-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "coder.imxyy.top" ];
}
{
name = "coder-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "coder.imxyy.top" ];
}
{
name = "grafana-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "grafana.imxyy.top" ];
}
{
name = "grafana-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "grafana.imxyy.top" ];
}
{
name = "siyuan-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "sy.imxyy.top" ];
}
{
name = "siyuan-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "sy.imxyy.top" ];
}
{
name = "matrix-root-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "imxyy.top" ];
}
{
name = "matrix-root-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "imxyy.top" ];
}
{
name = "matrix-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "matrix.imxyy.top" ];
}
{
name = "matrix-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "matrix.imxyy.top" ];
}
{
name = "immich-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "immich.imxyy.top" ];
}
{
name = "immich-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "immich.imxyy.top" ];
}
{
name = "memo-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "memo.imxyy.top" ];
}
{
name = "memo-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "memo.imxyy.top" ];
}
{
name = "efl-matrix-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "mtx.eflx.top" ];
}
{
name = "efl-matrix-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "mtx.eflx.top" ];
}
{
name = "efl-send-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "send.eflx.top" ];
}
{
name = "efl-send-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "send.eflx.top" ];
}
];
};
};
};
sops.secrets.et-imxyy-nix-server = {
sopsFile = secrets.et-imxyy-nix-server;
restartUnits = [ "easytier.service" ];
format = "binary";
};
environment.systemPackages = [ pkgs.easytier ];
systemd.services."easytier" = {
enable = true;
script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix-server.path}";
serviceConfig = {
Restart = "always";
RestartSec = 30;
User = "root";
};
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"sops-nix.service"
];
};
virtualisation.oci-containers.containers.obligator = {
image = "anderspitman/obligator:latest";
volumes = [
"/var/lib/obligator:/data"
"/var/lib/obligator:/api"
];
ports = [ "8081:1616" ];
cmd = [
"-storage-dir"
"/data"
"-api-socket-dir"
"/api"
"-root-uri"
"https://oidc.imxyy.top"
"-port"
"1616"
];
};
services.caddy.virtualHosts."oidc.imxyy.top" = {
extraConfig = ''
reverse_proxy :8081 {
header_up X-Real-IP {remote_host}
}
'';
};
systemd.services.ddns-go =
let
version = "6.6.7";
ddns-go = pkgs.buildGoModule {
inherit version;
pname = "ddns-go";
src = pkgs.fetchFromGitHub {
owner = "jeessy2";
repo = "ddns-go";
rev = "v${version}";
hash = "sha256-Ejoe6e9GFhHxQ9oIBDgDRQW9Xx1XZK+qSAXiRXLdn+c=";
};
meta.mainProgram = "ddns-go";
vendorHash = "sha256-XZii7gV3DmTunYyGYzt5xXhv/VpTPIoYKbW4LnmlAgs=";
doCheck = false;
};
in
{
description = "Go Dynamic DNS";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${lib.getExe ddns-go} -l :9876 -f 10 -cacheTimes 180 -c /var/lib/ddns-go/config.yaml";
Restart = "always";
RestartSec = 120;
};
path = [
pkgs.bash
];
};
services.dnsmasq =
let
subDomains = [
"home"
"nextcloud"
"mail"
"git"
"vault"
"coder"
"grafana"
"matrix"
"note"
"oidc"
"mc"
"music"
"sy"
"immich"
];
in
{
enable = true;
resolveLocalQueries = false;
settings = {
no-resolv = true;
server = [ "192.168.3.1" ];
address = map (sub: "/${sub}.imxyy.top/192.168.3.2") subDomains ++ [
"/imxyy-nix-server/192.168.3.2"
"/imxyy-cloudwin/192.168.3.4"
"/printer.home/192.168.3.53"
];
cache-size = 0;
log-queries = "extra";
};
};
}

View File

@@ -0,0 +1,152 @@
{
lib,
pkgs,
hostname,
...
}:
let
nextcloud = "nextcloud.${imxyy}";
imxyy = "imxyy.top";
in
{
environment.systemPackages = with pkgs; [
exiftool
ffmpeg
rclone
];
services.nextcloud = {
enable = true;
package = pkgs.nextcloud32;
extraApps = {
inherit (pkgs.nextcloud32.packages.apps)
bookmarks
previewgenerator
spreed
notes
registration
;
};
extraAppsEnable = true;
hostName = nextcloud;
home = "/mnt/nas/nextcloud";
https = true;
caching.redis = true;
configureRedis = true;
database.createLocally = true;
notify_push.enable = true;
config = {
dbtype = "pgsql";
adminpassFile = toString (pkgs.writeText "nextcloud-pass" "admin12345!");
adminuser = "admin";
};
settings = {
trusted_domains = [
hostname
"192.168.3.2"
"10.0.0.1"
];
trusted_proxies = [
"127.0.0.1"
"192.168.3.0/24"
];
};
phpExtraExtensions =
all: with all; [
pdlib
];
maxUploadSize = "16G";
phpOptions = {
"opcache.enable" = 1;
"opcache.enable_cli" = 1;
"opcache.interned_strings_buffer" = 23;
"opcache.max_accelerated_files" = 10000;
"opcache.memory_consumption" = 128;
"opcache.save_comments" = 1;
"opcache.revalidate_freq" = 1;
memory_limit = lib.mkForce "2G";
};
poolSettings = {
pm = "dynamic";
"pm.max_children" = "12";
"pm.min_spare_servers" = "6";
"pm.max_spare_servers" = "12";
};
};
services.nginx.virtualHosts."nextcloud.imxyy.top" = {
listen = [
{
addr = "0.0.0.0";
port = 8084;
}
];
};
/*
services.caddy.virtualHosts.":80" = {
extraConfig = ''
redir https://{host}{uri}
'';
};
services.caddy.virtualHosts.":443" = {
extraConfig =
let
path = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/nextcloud.imxyy.top";
in
''
reverse_proxy :8084
tls ${path}/nextcloud.imxyy.top.crt ${path}/nextcloud.imxyy.top.key
'';
};
*/
services.caddy.virtualHosts."nextcloud.imxyy.top" = {
extraConfig = ''
reverse_proxy http://127.0.0.1:8084 {
trusted_proxies 192.168.3.0/24
}
redir /.well-known/carddav /remote.php/dav/ 301
redir /.well-known/caldav /remote.php/dav/ 301
'';
};
/*
systemd.timers."kopia" = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
Unit = "kopia.service";
};
};
*/
systemd.services."kopia" = {
script = ''
${pkgs.kopia}/bin/kopia snapshot create /mnt/nas/share
${pkgs.kopia}/bin/kopia snapshot create /mnt/nas/nextcloud/data
'';
serviceConfig = {
Type = "oneshot";
User = "nextcloud";
};
};
systemd.timers."nextcloud-cronjobs" = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
Unit = "nextcloud-cronjobs.service";
};
};
systemd.services."nextcloud-cronjobs" = {
script = ''
/run/current-system/sw/bin/nextcloud-occ preview:pre-generate
'';
serviceConfig = {
Type = "oneshot";
User = "nextcloud";
};
};
}

View File

@@ -0,0 +1,14 @@
{
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
clientMaxBodySize = "0";
};
security.acme = {
acceptTerms = true;
defaults.email = "acme@imxyy.top";
};
}

View File

@@ -0,0 +1,17 @@
{
lib,
config,
username,
secrets,
...
}:
{
sops.secrets.imxyy-nix-server-hashed-password = {
sopsFile = secrets.imxyy-nix-server-hashed-password;
format = "binary";
neededForUsers = true;
};
users.users.${username}.hashedPasswordFile =
lib.mkForce config.sops.secrets.imxyy-nix-server-hashed-password.path;
users.users.root.hashedPasswordFile = lib.mkForce config.sops.secrets.imxyy-nix-server-hashed-password.path;
}

View File

@@ -0,0 +1,51 @@
{
config,
secrets,
...
}:
{
sops.secrets.siyuan-env = {
sopsFile = secrets.siyuan;
restartUnits = [ "siyuan.service" ];
format = "dotenv";
};
virtualisation.oci-containers.containers = {
siyuan = {
image = "apkdv/siyuan-unlock:v3.1.30";
volumes = [
"/mnt/nas/siyuan/workspace:/workspace"
"/mnt/nas/siyuan:/home/siyuan"
];
cmd = [
"--workspace=/workspace"
];
environment = {
PUID = "0";
PGID = "0";
};
environmentFiles = [
"${config.sops.secrets.siyuan-env.path}"
];
ports = [ "8095:6806" ];
};
memos = {
image = "neosmemo/memos:stable";
volumes = [
"/mnt/nas/memos:/var/opt/memos"
];
ports = [ "8097:5230" ];
};
};
services.caddy.virtualHosts = {
"sy.imxyy.top" = {
extraConfig = ''
reverse_proxy :8095
'';
};
"memo.imxyy.top" = {
extraConfig = ''
reverse_proxy :8097
'';
};
};
}

View File

@@ -0,0 +1,74 @@
{
inputs,
pkgs,
lib,
...
}:
let
app = pkgs.buildNpmPackage (finalAttrs: {
pname = "HF-plant";
version = "unstable-2025-09-21";
src = inputs.plant;
buildPhase = ''
runHook preBuild
npm run build
npm run build:proxy
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir $out
mv dist $out
cp .env proxy-server-bundled.js $out
runHook postInstall
'';
npmDepsHash = "sha256-ret4BtjrEt8L1nlvJmFiejAKmbz89Z7NSiKs+qlB51w=";
});
in
{
systemd.services.HF-plant-proxy = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${lib.getExe pkgs.bash} -c 'source ${app}/.env; export FEISHU_APP_ID FEISHU_APP_SECRET AMAP_JSCODE; ${lib.getExe pkgs.nodejs} ${app}/proxy-server-bundled.js'";
Restart = "always";
RestartSec = 120;
};
};
services.caddy.virtualHosts."plant.imxyy.top" = {
extraConfig = ''
handle /api/* {
reverse_proxy localhost:3001
}
handle /* {
root * ${app}/dist
try_files {path} /index.html
file_server
}
'';
};
services.frp.instances."".settings.proxies = [
{
name = "plant-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "plant.imxyy.top" ];
}
{
name = "plant-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "plant.imxyy.top" ];
}
];
}

View File

@@ -0,0 +1,55 @@
{ config, secrets, ... }:
let
redisUrl = config.services.redis.servers.rsshub.unixSocket;
in
{
sops.secrets.rsshub-env = {
sopsFile = secrets.rsshub;
restartUnits = [ "podman-rsshub.service" ];
format = "dotenv";
};
users.users.rsshub = {
home = "/var/empty";
group = "rsshub";
isSystemUser = true;
};
users.groups.rsshub.members = [ "rsshub" ];
services.redis.servers.rsshub = {
enable = true;
user = "rsshub";
};
virtualisation.oci-containers.containers.rsshub = {
image = "diygod/rsshub";
volumes = [
"${redisUrl}:${redisUrl}"
];
ports = [ "8100:1200" ];
networks = [ "podman" ];
environment = {
CACHE_TYPE = "redis";
REDIS_URL = "${redisUrl}";
};
environmentFiles = [ config.sops.secrets.rsshub-env.path ];
};
services.caddy.virtualHosts."rss.imxyy.top" = {
extraConfig = ''
reverse_proxy :8100
'';
};
services.frp.instances."".settings.proxies = [
{
name = "rsshub-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "rss.imxyy.top" ];
}
{
name = "rsshub-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "rss.imxyy.top" ];
}
];
}

View File

@@ -0,0 +1,34 @@
{
services.samba = {
enable = true;
nsswins = true;
settings = {
global = {
security = "user";
"netbios name" = "NAS";
};
share = {
path = "/mnt/nas/share";
browsable = "yes";
"read only" = "no";
"guest ok" = "no";
"create mask" = "0664";
"directory mask" = "0775";
"force user" = "nextcloud";
"force group" = "nextcloud";
};
};
};
services.samba-wsdd.enable = true;
# ensure dir exists
systemd.tmpfiles.rules = [
"d /mnt/nas/share 0775 nextcloud nextcloud - -"
];
users = {
users.nas = {
isSystemUser = true;
description = "NAS user";
group = "nextcloud";
};
};
}

View File

@@ -0,0 +1,49 @@
{ config, secrets, ... }:
{
sops.secrets.sshwifty = {
sopsFile = secrets.sshwifty;
format = "binary";
};
services.sshwifty = {
enable = true;
sharedKeyFile = config.sops.secrets.sshwifty.path;
settings = {
Servers = [
{
ListenInterface = "0.0.0.0";
ListenPort = 8101;
InitialTimeout = 10;
ReadTimeout = 120;
WriteTimeout = 120;
HeartbeatTimeout = 10;
ReadDelay = 10;
WriteDelay = 10;
TLSCertificateFile = "";
TLSCertificateKeyFile = "";
ServerMessage = "";
}
];
};
};
services.caddy.virtualHosts."ssh.imxyy.top" = {
extraConfig = ''
reverse_proxy :8101
'';
};
services.frp.instances."".settings.proxies = [
{
name = "sshwifty-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "ssh.imxyy.top" ];
}
{
name = "sshwifty-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "ssh.imxyy.top" ];
}
];
}

View File

@@ -0,0 +1,32 @@
{ config, secrets, ... }:
{
sops.secrets.vaultwarden-env = {
sopsFile = secrets.vaultwarden;
restartUnits = [ "vaultwarden.service" ];
format = "dotenv";
};
services.postgresql.ensureUsers = [
{
name = "vaultwarden";
ensureDBOwnership = true;
}
];
services.postgresql.ensureDatabases = [ "vaultwarden" ];
services.vaultwarden = {
enable = true;
dbBackend = "postgresql";
config = {
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8083;
DOMAIN = "https://vault.imxyy.top";
};
environmentFile = "${config.sops.secrets.vaultwarden-env.path}";
};
services.caddy.virtualHosts."vault.imxyy.top" = {
extraConfig = ''
reverse_proxy :8083 {
header_up X-Real-IP {remote_host}
}
'';
};
}

View File

@@ -0,0 +1,33 @@
{ lib, ... }:
let
# T400
gpuIDs = [
"8086:56a0" # A770
"8086:4f90"
"10de:1f82" # 1650
"10de:10fa"
"10de:1fb2" # T400
];
in
{
boot = {
initrd.kernelModules = lib.mkBefore [
"vfio_pci"
"vfio"
"vfio_iommu_type1"
];
kernelParams = [
"pcie_acs_override=downstream,multifunction"
"amd_iommu=on"
"vfio-pci.ids=${lib.concatStringsSep "," gpuIDs}"
];
extraModprobeConfig = ''
options kvm ignore_msrs=Y
options kvm report_ignored_msrs=N
'';
};
virtualisation.spiceUSBRedirection.enable = true;
my.virt.enable = true;
}

View File

@@ -0,0 +1,14 @@
{ lib, username, ... }:
{
my.hm.programs.zsh.shellAliases = {
localproxy_on = "export http_proxy=http://192.168.128.1:7890 https_proxy=http://192.168.128.1:7890 all_proxy=socks://192.168.128.1:7890";
};
my = {
sops.sshKeyFile = "/home/${username}/.ssh/id_ed25519";
coding.all.enable = true;
coding.editor.vscode.enable = lib.mkForce false;
cli.misc.enable = true;
xdg.enable = true;
cli.media.all.enable = true;
};
}

View File

@@ -0,0 +1,27 @@
{
lib,
username,
inputs,
...
}:
{
imports = [
inputs.nixos-wsl.nixosModules.wsl
];
wsl.enable = true;
wsl.defaultUser = username;
services.openssh = {
enable = true;
settings = {
# Forbid root login through SSH.
PermitRootLogin = "no";
PasswordAuthentication = true;
};
};
# fix vscode remote
programs.nix-ld.enable = true;
nixpkgs.hostPlatform = lib.mkForce "x86_64-linux";
}

View File

@@ -0,0 +1,108 @@
{
config,
lib,
pkgs,
...
}:
let
btrfs = "/dev/disk/by-uuid/69ab72d4-6ced-4f70-8b5e-aa2daa8c0b6b";
in
{
boot = {
initrd = {
kernelModules = [ "amdgpu" ];
availableKernelModules = [
"nvme"
"xhci_pci"
"thunderbolt"
"uas"
"sd_mod"
];
verbose = false;
};
kernelPackages = lib.mkForce pkgs.linuxPackages_xanmod_latest;
kernelModules = [ "kvm-amd" ];
tmp.useTmpfs = true;
kernel.sysctl = {
"fs.file-max" = 9223372036854775807;
};
};
services.scx = {
enable = true;
scheduler = "scx_rusty";
};
fileSystems."/" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=root"
];
};
fileSystems."/nix" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=nix"
];
};
my.persist.location = "/nix/persist";
fileSystems."/nix/persist" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=persist"
];
neededForBoot = true;
};
boot.initrd.postDeviceCommands = lib.mkAfter ''
mkdir /btrfs_tmp
mount ${btrfs} /btrfs_tmp
mkdir -p /btrfs_tmp/old_roots
if [[ -e /btrfs_tmp/root ]]; then
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +14); do
delete_subvolume_recursively "$i"
done
btrfs subvolume create /btrfs_tmp/root
umount /btrfs_tmp
'';
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/96D3-93B0";
fsType = "vfat";
options = [
"uid=0"
"gid=0"
"fmask=0077"
"dmask=0077"
];
};
networking.useDHCP = lib.mkDefault false;
hardware.enableRedistributableFirmware = lib.mkDefault true;
hardware.cpu.amd.updateMicrocode = config.hardware.enableRedistributableFirmware;
nixpkgs.hostPlatform = lib.mkForce "x86_64-linux";
}

View File

@@ -0,0 +1,141 @@
{
config,
pkgs,
username,
...
}:
{
my.hm = {
home.packages = with pkgs; [
localsend
wpsoffice-cn
wps-office-fonts
ttf-wps-fonts
papers
anki
ayugram-desktop
signal-desktop
element-desktop
fractal
qq
wechat
gnome-clocks
];
programs.zsh = {
sessionVariables = {
PATH = "/home/${username}/bin:$PATH";
};
};
programs.niri.settings = {
environment.STEAM_FORCE_DESKTOPUI_SCALING = "1.25";
outputs = {
eDP-1 = {
enable = true;
mode = {
width = 1920;
height = 1200;
refresh = 60.002;
};
scale = 1.25;
};
};
};
};
my = {
gpg.enable = true;
cli.all.enable = true;
coding.all.enable = true;
desktop.all.enable = true;
virt.moonlight.enable = true;
i18n.fcitx5.enable = true;
xdg = {
enable = true;
defaultApplications =
let
browser = [ config.my.desktop.browser.default.desktop ];
editor = [ "codium.desktop" ];
imageviewer = [ "org.gnome.Shotwell-Viewer.desktop" ];
in
{
"inode/directory" = [ "org.gnome.Nautilus.desktop" ];
"application/pdf" = [ "org.gnome.Papers.desktop" ];
"text/*" = editor;
"application/json" = editor;
"text/html" = editor;
"text/xml" = editor;
"application/xml" = editor;
"application/xhtml+xml" = editor;
"application/xhtml_xml" = editor;
"application/rdf+xml" = editor;
"application/rss+xml" = editor;
"application/x-extension-htm" = editor;
"application/x-extension-html" = editor;
"application/x-extension-shtml" = editor;
"application/x-extension-xht" = editor;
"application/x-extension-xhtml" = editor;
"x-scheme-handler/about" = browser;
"x-scheme-handler/ftp" = browser;
"x-scheme-handler/http" = browser;
"x-scheme-handler/https" = browser;
"x-scheme-handler/unknown" = browser;
"audio/*" = imageviewer;
"video/*" = imageviewer;
"image/*" = imageviewer;
"image/gif" = imageviewer;
"image/jpeg" = imageviewer;
"image/png" = imageviewer;
"image/webp" = imageviewer;
};
};
persist = {
enable = true;
homeDirs = [
"Documents"
"Downloads"
"Videos"
"Music"
"Pictures"
"bin"
"workspace"
".cache"
".local/state"
".local/share/Anki2"
".local/share/shotwell"
".local/share/Kingsoft"
".local/share/AyuGramDesktop"
".local/share/fractal"
".config/Signal"
".config/Element"
".config/QQ"
".xwechat"
".config/Kingsoft"
".config/dconf"
".config/pip"
".config/sunshine"
".gemini"
".claude"
".claude-code-router"
];
homeFiles = [
".claude.json"
];
};
};
}

101
hosts/imxyy-nix-x16/net.nix Normal file
View File

@@ -0,0 +1,101 @@
{
config,
pkgs,
secrets,
...
}:
{
boot.kernelParams = [
"biosdevname=0"
"net.ifnames=0"
];
my.persist.nixosDirs = [ "/etc/NetworkManager/system-connections" ];
networking = {
networkmanager.enable = true;
firewall.enable = false;
nftables = {
enable = true;
flushRuleset = true;
ruleset = ''
table inet firewall {
set LANv4 {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
}
set LANv6 {
type ipv6_addr
flags interval
elements = { fd00::/8, fe80::/10 }
}
chain output {
type filter hook output priority 100; policy accept;
}
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state invalid drop
ct state established,related accept
ip saddr @LANv4 accept
ip6 saddr @LANv6 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
}
'';
};
};
sops.secrets.dae-imxyy-nix-x16 = {
sopsFile = secrets.dae-imxyy-nix-x16;
restartUnits = [ "dae.service" ];
format = "binary";
};
services.dae = {
enable = true;
configFile = config.sops.secrets.dae-imxyy-nix-x16.path;
};
systemd.services.dae.after = [ "sops-nix.service" ];
sops.secrets.mihomo = {
sopsFile = secrets.mihomo;
restartUnits = [ "mihomo.service" ];
format = "yaml";
key = "";
};
systemd.services.mihomo.after = [ "sops-nix.service" ];
services.mihomo = {
enable = true;
configFile = config.sops.secrets.mihomo.path;
webui = pkgs.metacubexd;
};
sops.secrets.et-imxyy-nix-x16 = {
sopsFile = secrets.et-imxyy-nix-x16;
restartUnits = [ "easytier.service" ];
format = "binary";
};
environment.systemPackages = with pkgs; [
easytier
];
systemd.services."easytier" = {
enable = true;
script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix-x16.path}";
serviceConfig = {
Restart = "always";
RestartSec = 30;
User = "root";
};
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"sops-nix.service"
];
};
}

View File

@@ -0,0 +1,67 @@
{
pkgs,
config,
username,
secrets,
...
}:
{
boot.kernelParams = [
"usbcore.autosuspend=-1" # Avoid usb autosuspend (for usb bluetooth adapter)
];
services.upower.enable = true;
services.power-profiles-daemon.enable = true;
services.keyd = {
enable = true;
keyboards.default.settings = {
main = {
capslock = "overload(control, esc)";
home = "end";
};
shift = {
home = "home";
};
control = {
delete = "print";
};
};
};
services.openssh = {
enable = true;
settings = {
# Forbid root login through SSH.
PermitRootLogin = null;
PasswordAuthentication = true;
};
};
environment.systemPackages = [
pkgs.rclone
];
sops.secrets.imxyy-nix-rclone = {
sopsFile = secrets.imxyy-nix-rclone;
format = "binary";
};
fileSystems = {
"/home/${username}/Nextcloud" = {
device = "Nextcloud:";
fsType = "rclone";
options = [
"nodev"
"nofail"
"allow_other"
"args2env"
"config=${config.sops.secrets.imxyy-nix-rclone.path}"
"uid=1000"
"gid=100"
"rw"
"no-check-certificate"
"vfs-cache-mode=full"
];
};
};
}

View File

@@ -0,0 +1,165 @@
{
config,
lib,
pkgs,
username,
...
}:
let
btrfs = "/dev/disk/by-uuid/0404de0a-9c4d-4c98-b3e5-b8ff8115f36c";
in
{
boot = {
initrd = {
kernelModules = [ "amdgpu" ];
availableKernelModules = [
"xhci_pci"
"ahci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
];
verbose = false;
};
kernelPackages = lib.mkForce pkgs.linuxPackages_xanmod_latest;
kernelModules = [ "kvm-amd" ];
tmp.useTmpfs = true;
kernel.sysctl = {
"fs.file-max" = 9223372036854775807;
};
resumeDevice = btrfs;
kernelParams = [
"resume_offset=6444127"
];
};
services.scx = {
enable = true;
scheduler = "scx_rusty";
};
fileSystems."/" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=root"
];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/843c36ae-f6d0-46a1-b5c7-8ab569e1e63f";
fsType = "btrfs";
options = [ "compress=zstd" ];
};
my.persist.location = "/nix/persist";
fileSystems."/nix/persist" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=persistent"
];
neededForBoot = true;
};
fileSystems."/swap" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=swap"
];
neededForBoot = true;
};
boot.initrd.postDeviceCommands = lib.mkAfter ''
mkdir /btrfs_tmp
mount ${btrfs} /btrfs_tmp
mkdir -p /btrfs_tmp/old_roots
if [[ -e /btrfs_tmp/root ]]; then
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +14); do
delete_subvolume_recursively "$i"
done
btrfs subvolume create /btrfs_tmp/root
umount /btrfs_tmp
'';
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/B7DC-E9AC";
fsType = "vfat";
options = [
"uid=0"
"gid=0"
"fmask=0077"
"dmask=0077"
];
};
fileSystems."/home/${username}/Documents" = {
device = "/dev/disk/by-uuid/a4e37dcd-764a-418c-aa1c-484f1fbd4bbe";
fsType = "ext4";
};
fileSystems."/home/${username}/Downloads" = {
device = "/dev/disk/by-uuid/18717cb4-49ac-40fa-95d4-29523a458dd0";
fsType = "ext4";
};
fileSystems."/home/${username}/Videos" = {
device = "/dev/disk/by-uuid/b67bbeab-58bc-4814-b5e3-08404e78b25e";
fsType = "ext4";
};
fileSystems."/home/${username}/Pictures" = {
device = "/dev/disk/by-uuid/a31bfe7e-cc17-4bd2-af74-ae5de9be35d3";
fsType = "ext4";
};
fileSystems."/home/${username}/Music" = {
device = "//192.168.3.2/share/imxyy_soope_/Music";
fsType = "cifs";
options = [
"username=nas"
"password=nasshare"
"x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s"
"nodev"
"nofail"
"uid=1000"
"gid=100"
"vers=3"
"rw"
];
};
swapDevices = [
{
device = "/swap/swapfile";
size = 32 * 1024;
}
];
networking.useDHCP = lib.mkDefault false;
hardware.enableRedistributableFirmware = lib.mkDefault true;
hardware.cpu.amd.updateMicrocode = config.hardware.enableRedistributableFirmware;
nixpkgs.hostPlatform = lib.mkForce "x86_64-linux";
}

168
hosts/imxyy-nix/home.nix Normal file
View File

@@ -0,0 +1,168 @@
{
config,
pkgs,
username,
...
}:
{
my.hm = {
home.packages = with pkgs; [
localsend
wpsoffice-cn
wps-office-fonts
ttf-wps-fonts
papers
anki
ayugram-desktop
signal-desktop
element-desktop
fractal
qq
wechat
gnome-clocks
];
programs.zsh = {
shellAliases = {
cageterm = "cage -m DP-1 -s -- alacritty -o font.size=20";
cagefoot = "cage -m DP-1 -s -- foot --font=monospace:size=20";
cagekitty = "cage -m DP-1 -s -- kitty -o font_size=20";
};
sessionVariables = {
no_proxy = "192.168.3.0/24";
PATH = "/home/${username}/bin:$PATH";
};
profileExtra = ''
if [ `tty` = "/dev/tty6" ]; then
clear
fi
'';
};
programs.niri.settings = {
environment.STEAM_FORCE_DESKTOPUI_SCALING = "1.25";
outputs = {
DP-1 = {
enable = true;
mode = {
width = 2560;
height = 1440;
refresh = 75.033;
};
scale = 1.25;
position = {
x = 0;
y = 0;
};
};
DP-2 = {
enable = true;
mode = {
width = 2560;
height = 1440;
refresh = 75.033;
};
scale = 1.25;
};
};
};
};
my = {
autologin = {
enable = true;
user = username;
ttys = [ 6 ];
};
gpg.enable = true;
cli.all.enable = true;
coding.all.enable = true;
desktop.all.enable = true;
i18n.fcitx5.enable = true;
xdg = {
enable = true;
defaultApplications =
let
browser = [ config.my.desktop.browser.default.desktop ];
editor = [ "codium.desktop" ];
imageviewer = [ "org.gnome.Shotwell-Viewer.desktop" ];
in
{
"inode/directory" = [ "org.gnome.Nautilus.desktop" ];
"application/pdf" = [ "org.gnome.Papers.desktop" ];
"text/*" = editor;
"application/json" = editor;
"text/html" = editor;
"text/xml" = editor;
"application/xml" = editor;
"application/xhtml+xml" = editor;
"application/xhtml_xml" = editor;
"application/rdf+xml" = editor;
"application/rss+xml" = editor;
"application/x-extension-htm" = editor;
"application/x-extension-html" = editor;
"application/x-extension-shtml" = editor;
"application/x-extension-xht" = editor;
"application/x-extension-xhtml" = editor;
"x-scheme-handler/about" = browser;
"x-scheme-handler/ftp" = browser;
"x-scheme-handler/http" = browser;
"x-scheme-handler/https" = browser;
"x-scheme-handler/unknown" = browser;
"audio/*" = imageviewer;
"video/*" = imageviewer;
"image/*" = imageviewer;
"image/gif" = imageviewer;
"image/jpeg" = imageviewer;
"image/png" = imageviewer;
"image/webp" = imageviewer;
};
};
persist = {
enable = true;
homeDirs = [
".android"
"Android"
"bin"
"workspace"
"Virt"
".cache"
".local/state"
".local/share/Anki2"
".local/share/shotwell"
".local/share/Kingsoft"
".local/share/AyuGramDesktop"
".local/share/fractal"
".config/Signal"
".config/Element"
".config/QQ"
".xwechat"
".config/Kingsoft"
".config/dconf"
".config/pip"
".config/sunshine"
".gemini"
".claude"
".claude-code-router"
];
homeFiles = [
".claude.json"
];
};
};
}

134
hosts/imxyy-nix/net.nix Normal file
View File

@@ -0,0 +1,134 @@
{
config,
lib,
pkgs,
secrets,
...
}:
{
boot.kernelParams = [
"biosdevname=0"
"net.ifnames=0"
];
networking = {
useDHCP = lib.mkForce false;
dhcpcd = {
wait = "background";
IPv6rs = true;
extraConfig = ''
interface eth0
noipv4
'';
};
interfaces = {
eth0 = {
useDHCP = lib.mkForce true;
wakeOnLan.enable = true;
macAddress = "3C:7C:3F:7C:D3:9D";
ipv4 = {
addresses = [
{
address = "192.168.3.3";
prefixLength = 24;
}
];
};
};
};
defaultGateway = {
address = "192.168.3.1";
interface = "eth0";
};
nameservers = [
"192.168.3.2"
];
firewall.enable = false;
nftables = {
enable = true;
flushRuleset = true;
ruleset = ''
table inet firewall {
set LANv4 {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
}
set LANv6 {
type ipv6_addr
flags interval
elements = { fd00::/8, fe80::/10 }
}
chain output {
type filter hook output priority 100; policy accept;
}
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
iifname waydroid0 accept
ct state invalid drop
ct state established,related accept
ip saddr @LANv4 accept
ip6 saddr @LANv6 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
iifname waydroid0 accept
oifname waydroid0 accept
}
}
'';
};
};
sops.secrets.dae-imxyy-nix = {
sopsFile = secrets.dae-imxyy-nix;
restartUnits = [ "dae.service" ];
format = "binary";
};
services.dae = {
enable = true;
configFile = config.sops.secrets.dae-imxyy-nix.path;
};
systemd.services.dae.after = [ "sops-nix.service" ];
sops.secrets.mihomo = {
sopsFile = secrets.mihomo;
restartUnits = [ "mihomo.service" ];
format = "yaml";
key = "";
};
systemd.services.mihomo.after = [ "sops-nix.service" ];
services.mihomo = {
enable = true;
configFile = config.sops.secrets.mihomo.path;
webui = pkgs.metacubexd;
};
sops.secrets.et-imxyy-nix = {
sopsFile = secrets.et-imxyy-nix;
restartUnits = [ "easytier.service" ];
format = "binary";
};
environment.systemPackages = [ pkgs.easytier ];
systemd.services."easytier" = {
enable = true;
script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix.path}";
serviceConfig = {
Restart = "always";
RestartSec = 30;
User = "root";
};
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"sops-nix.service"
];
};
}

130
hosts/imxyy-nix/nixos.nix Normal file
View File

@@ -0,0 +1,130 @@
{
lib,
pkgs,
config,
username,
secrets,
...
}:
let
btreset = pkgs.writeShellScriptBin "btreset" ''
LOCKFILE="/tmp/.btreseted"
SYM="BT"
if [ -f "$LOCKFILE" ] && [ "$1" != "-f" ]; then
exit 0
fi
${lib.getExe' pkgs.usbutils "lsusb"} | grep "$SYM" | while read -r line; do
bus=$(echo "$line" | awk '{print $2}')
dev=$(echo "$line" | awk '{print $4}' | tr -d ':')
${lib.getExe' pkgs.usbutils "usbreset"} "$bus/$dev"
touch "$LOCKFILE"
done
'';
in
{
systemd.services.btreset = {
script = lib.getExe btreset;
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
};
boot.kernelParams = [
"usbcore.autosuspend=-1" # Avoid usb autosuspend (for usb bluetooth adapter)
"fsck.mode=skip"
];
services.keyd = {
enable = true;
keyboards = {
default.settings = {
main = {
capslock = "overload(control, esc)";
home = "end";
};
shift = {
home = "home";
};
control = {
delete = "print";
};
};
kone-pro-owl-eye = {
ids = [ "1e7d:2dcd" ];
settings.main.mouse2 = "rightmouse";
};
};
};
programs.wireshark.enable = true;
programs.wireshark.package = pkgs.wireshark;
users.users.${username}.extraGroups = [ "wireshark" ];
virtualisation.waydroid.enable = true;
my.persist.homeDirs = [ ".local/share/waydroid" ];
services.sunshine = {
enable = true;
autoStart = true;
capSysAdmin = true;
applications.apps = [
{
name = "Desktop";
image-path = "desktop.png";
}
];
};
services.openssh = {
enable = true;
settings = {
# Forbid root login through SSH.
PermitRootLogin = null;
PasswordAuthentication = true;
};
};
environment.systemPackages = [
pkgs.rclone
btreset
];
sops.secrets.imxyy-nix-rclone = {
sopsFile = secrets.imxyy-nix-rclone;
format = "binary";
};
fileSystems = {
"/home/${username}/Nextcloud" = {
device = "Nextcloud:";
fsType = "rclone";
options = [
"nodev"
"nofail"
"allow_other"
"args2env"
"config=${config.sops.secrets.imxyy-nix-rclone.path}"
"uid=1000"
"gid=100"
"rw"
"no-check-certificate"
"vfs-cache-mode=full"
];
};
"/home/${username}/NAS" = {
device = "//192.168.3.2/share";
fsType = "cifs";
options = [
"username=nas"
"password=nasshare"
"x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s"
"nodev"
"nofail"
"uid=1000"
"gid=100"
"vers=3"
"rw"
];
};
};
}

View File

@@ -0,0 +1,36 @@
{
lib,
pkgs,
username,
...
}:
{
virtualisation.podman = {
enable = true;
dockerCompat = true;
dockerSocket.enable = true;
};
users.users.${username}.extraGroups = [ "podman" ];
environment.systemPackages = [ pkgs.distrobox ];
my.hm.programs.distrobox = {
enable = true;
settings = {
container_image_default = "docker.io/archlinux:latest";
};
containers = {
archlinux = {
image = "archlinux:latest";
additional_packages = "nvim";
};
};
};
my.hm.programs.zsh.initContent = lib.mkBefore ''
if [ -n "''${CONTAINER_ID+1}" ]; then
export ZSH_DISABLE_COMPFIX=true
fi
'';
my.persist.homeDirs = [
".config/containers"
".local/share/containers"
];
}

12
hosts/imxyy-nix/virt.nix Normal file
View File

@@ -0,0 +1,12 @@
{
...
}:
{
hardware.graphics.enable = true;
virtualisation.spiceUSBRedirection.enable = true;
my.virt = {
enable = true;
moonlight.enable = true;
};
}