Initial commit
This commit is contained in:
commit
430194beda
109 changed files with 9066 additions and 0 deletions
8
modules/nixos/comin/default.nix
Normal file
8
modules/nixos/comin/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [ inputs.comin.nixosModules.comin ];
|
||||
}
|
||||
15
modules/nixos/common/default.nix
Normal file
15
modules/nixos/common/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
imports = [
|
||||
./environment.nix
|
||||
./htop.nix
|
||||
./nationalization.nix
|
||||
./networking.nix
|
||||
./nix.nix
|
||||
./sudo.nix
|
||||
./well-known.nix
|
||||
./zsh.nix
|
||||
|
||||
./shared
|
||||
./overlays.nix
|
||||
];
|
||||
}
|
||||
63
modules/nixos/common/environment.nix
Normal file
63
modules/nixos/common/environment.nix
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mkDefault optionals;
|
||||
in
|
||||
{
|
||||
environment.systemPackages =
|
||||
with pkgs;
|
||||
[
|
||||
cryptsetup
|
||||
curl
|
||||
dig
|
||||
dnsutils
|
||||
fzf
|
||||
gptfdisk
|
||||
iproute2
|
||||
jq
|
||||
lm_sensors
|
||||
lsof
|
||||
netcat-openbsd
|
||||
nettools
|
||||
nixos-container
|
||||
nmap
|
||||
nurl
|
||||
p7zip
|
||||
pciutils
|
||||
psmisc
|
||||
rclone
|
||||
rsync
|
||||
tcpdump
|
||||
tmux
|
||||
tree
|
||||
unzip
|
||||
usbutils
|
||||
wget
|
||||
xxd
|
||||
zip
|
||||
|
||||
(callPackage ../../../apps/rebuild { })
|
||||
]
|
||||
++ optionals (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) [
|
||||
pkgs.kitty.terminfo
|
||||
];
|
||||
|
||||
environment.shellAliases = {
|
||||
l = "ls -lh";
|
||||
ll = "ls -lAh";
|
||||
ports = "ss -tulpn";
|
||||
publicip = "curl ifconfig.me/all";
|
||||
sudo = "sudo "; # make aliases work with `sudo`
|
||||
};
|
||||
|
||||
# saves one instance of nixpkgs.
|
||||
environment.ldso32 = null;
|
||||
|
||||
boot.tmp.cleanOnBoot = mkDefault true;
|
||||
boot.initrd.systemd.enable = mkDefault (!config.boot.swraid.enable && !config.boot.isContainer);
|
||||
}
|
||||
8
modules/nixos/common/htop.nix
Normal file
8
modules/nixos/common/htop.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
programs.htop = {
|
||||
enable = true;
|
||||
settings = {
|
||||
highlight_base_name = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
31
modules/nixos/common/nationalization.nix
Normal file
31
modules/nixos/common/nationalization.nix
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{ lib, ... }:
|
||||
|
||||
let
|
||||
de = "de_DE.UTF-8";
|
||||
en = "en_US.UTF-8";
|
||||
|
||||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
i18n = {
|
||||
defaultLocale = mkDefault en;
|
||||
extraLocaleSettings = {
|
||||
LC_ADDRESS = mkDefault de;
|
||||
LC_IDENTIFICATION = mkDefault de;
|
||||
LC_MEASUREMENT = mkDefault de;
|
||||
LC_MONETARY = mkDefault de;
|
||||
LC_NAME = mkDefault de;
|
||||
LC_NUMERIC = mkDefault de;
|
||||
LC_PAPER = mkDefault de;
|
||||
LC_TELEPHONE = mkDefault de;
|
||||
LC_TIME = mkDefault en;
|
||||
};
|
||||
};
|
||||
|
||||
console = {
|
||||
font = mkDefault "Lat2-Terminus16";
|
||||
keyMap = mkDefault "de";
|
||||
};
|
||||
|
||||
time.timeZone = mkDefault "Europe/Berlin";
|
||||
}
|
||||
40
modules/nixos/common/networking.nix
Normal file
40
modules/nixos/common/networking.nix
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mkDefault;
|
||||
inherit (lib.utils) isNotEmptyStr;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
assertions = [
|
||||
{
|
||||
assertion = isNotEmptyStr config.networking.domain;
|
||||
message = "synix/nixos/common: config.networking.domain cannot be empty.";
|
||||
}
|
||||
{
|
||||
assertion = isNotEmptyStr config.networking.hostName;
|
||||
message = "synix/nixos/common: config.networking.hostName cannot be empty.";
|
||||
}
|
||||
];
|
||||
|
||||
networking = {
|
||||
domain = mkDefault "${config.networking.hostName}.local";
|
||||
hostId = mkDefault "8425e349"; # same as NixOS install ISO and nixos-anywhere
|
||||
|
||||
# NetworkManager
|
||||
useDHCP = false;
|
||||
networkmanager = {
|
||||
enable = true;
|
||||
plugins = with pkgs; [
|
||||
networkmanager-openconnect
|
||||
networkmanager-openvpn
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
19
modules/nixos/common/nix.nix
Normal file
19
modules/nixos/common/nix.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
nix = {
|
||||
# use flakes
|
||||
channel.enable = mkDefault false;
|
||||
|
||||
# De-duplicate store paths using hardlinks except in containers
|
||||
# where the store is host-managed.
|
||||
optimise.automatic = mkDefault (!config.boot.isContainer);
|
||||
};
|
||||
}
|
||||
10
modules/nixos/common/overlays.nix
Normal file
10
modules/nixos/common/overlays.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{ outputs, ... }:
|
||||
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
outputs.overlays.local-packages
|
||||
outputs.overlays.modifications
|
||||
outputs.overlays.old-stable-packages
|
||||
outputs.overlays.unstable-packages
|
||||
];
|
||||
}
|
||||
5
modules/nixos/common/shared/default.nix
Normal file
5
modules/nixos/common/shared/default.nix
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./nix.nix
|
||||
];
|
||||
}
|
||||
85
modules/nixos/common/shared/nix.nix
Normal file
85
modules/nixos/common/shared/nix.nix
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
optional
|
||||
versionOlder
|
||||
versions
|
||||
;
|
||||
in
|
||||
{
|
||||
nix.package = mkDefault pkgs.nix;
|
||||
|
||||
# for `nix run synix#foo`, `nix build synix#bar`, etc
|
||||
nix.registry = {
|
||||
synix = {
|
||||
from = {
|
||||
id = "synix";
|
||||
type = "indirect";
|
||||
};
|
||||
to = {
|
||||
owner = "sid";
|
||||
repo = "synix";
|
||||
host = "git.sid.ovh";
|
||||
type = "gitea";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# fallback quickly if substituters are not available.
|
||||
nix.settings.connect-timeout = mkDefault 5;
|
||||
nix.settings.fallback = true;
|
||||
|
||||
nix.settings.experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
]
|
||||
++ optional (
|
||||
config.nix.package != null && versionOlder (versions.majorMinor config.nix.package.version) "2.22"
|
||||
) "repl-flake";
|
||||
|
||||
nix.settings.log-lines = mkDefault 25;
|
||||
|
||||
# avoid disk full issues
|
||||
nix.settings.max-free = mkDefault (3000 * 1024 * 1024);
|
||||
nix.settings.min-free = mkDefault (512 * 1024 * 1024);
|
||||
|
||||
# avoid copying unnecessary stuff over SSH
|
||||
nix.settings.builders-use-substitutes = true;
|
||||
|
||||
# workaround for https://github.com/NixOS/nix/issues/9574
|
||||
nix.settings.nix-path = config.nix.nixPath;
|
||||
|
||||
nix.settings.download-buffer-size = 524288000; # 500 MiB
|
||||
|
||||
# add all wheel users to the trusted-users group
|
||||
nix.settings.trusted-users = [
|
||||
"@wheel"
|
||||
];
|
||||
|
||||
# binary caches
|
||||
nix.settings.substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://nix-community.cachix.org"
|
||||
"https://cache.garnix.io"
|
||||
"https://numtide.cachix.org"
|
||||
];
|
||||
nix.settings.trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
|
||||
"numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE="
|
||||
];
|
||||
|
||||
nix.gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 30d";
|
||||
};
|
||||
}
|
||||
26
modules/nixos/common/sudo.nix
Normal file
26
modules/nixos/common/sudo.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
execWheelOnly = true;
|
||||
extraConfig = ''
|
||||
Defaults lecture = never
|
||||
'';
|
||||
};
|
||||
|
||||
assertions =
|
||||
let
|
||||
validUsers = users: users == [ ] || users == [ "root" ];
|
||||
validGroups = groups: groups == [ ] || groups == [ "wheel" ];
|
||||
validUserGroups = builtins.all (
|
||||
r: validUsers (r.users or [ ]) && validGroups (r.groups or [ ])
|
||||
) config.security.sudo.extraRules;
|
||||
in
|
||||
[
|
||||
{
|
||||
assertion = config.security.sudo.execWheelOnly -> validUserGroups;
|
||||
message = "Some definitions in `security.sudo.extraRules` refer to users other than 'root' or groups other than 'wheel'. Disable `config.security.sudo.execWheelOnly`, or adjust the rules.";
|
||||
}
|
||||
];
|
||||
}
|
||||
17
modules/nixos/common/well-known.nix
Normal file
17
modules/nixos/common/well-known.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
# avoid TOFU MITM
|
||||
programs.ssh.knownHosts = {
|
||||
"github.com".hostNames = [ "github.com" ];
|
||||
"github.com".publicKey =
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||
|
||||
"gitlab.com".hostNames = [ "gitlab.com" ];
|
||||
"gitlab.com".publicKey =
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf";
|
||||
|
||||
"git.sr.ht".hostNames = [ "git.sr.ht" ];
|
||||
"git.sr.ht".publicKey =
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60";
|
||||
};
|
||||
# TODO: add synix
|
||||
}
|
||||
26
modules/nixos/common/zsh.nix
Normal file
26
modules/nixos/common/zsh.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
programs.zsh = {
|
||||
enable = true;
|
||||
syntaxHighlighting = {
|
||||
enable = true;
|
||||
highlighters = [
|
||||
"main"
|
||||
"brackets"
|
||||
"cursor"
|
||||
"pattern"
|
||||
];
|
||||
patterns = {
|
||||
"rm -rf" = "fg=white,bold,bg=red";
|
||||
"rm -fr" = "fg=white,bold,bg=red";
|
||||
};
|
||||
};
|
||||
autosuggestions = {
|
||||
enable = true;
|
||||
strategy = [
|
||||
"completion"
|
||||
"history"
|
||||
];
|
||||
};
|
||||
enableLsColors = true;
|
||||
};
|
||||
}
|
||||
13
modules/nixos/default.nix
Normal file
13
modules/nixos/default.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
common = import ./common;
|
||||
comin = import ./comin;
|
||||
forgejo = import ./forgejo;
|
||||
forgejo-runner = import ./forgejo-runner;
|
||||
mailserver = import ./mailserver;
|
||||
nixvim = import ./nixvim;
|
||||
normalUsers = import ./normalUsers;
|
||||
nginx = import ./nginx;
|
||||
openssh = import ./openssh;
|
||||
sops = import ./sops;
|
||||
tailscale = import ./tailscale;
|
||||
}
|
||||
68
modules/nixos/forgejo-runner/default.nix
Normal file
68
modules/nixos/forgejo-runner/default.nix
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.forgejo-runner;
|
||||
|
||||
inherit (lib)
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.forgejo-runner = {
|
||||
enable = mkEnableOption "Nix-based Forgejo Runner service";
|
||||
url = mkOption {
|
||||
type = types.str;
|
||||
description = "Forgejo instance URL.";
|
||||
};
|
||||
tokenFile = mkOption {
|
||||
type = types.path;
|
||||
description = "Path to EnvironmentFile containing TOKEN=...";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
nix.settings.trusted-users = [ "gitea-runner" ];
|
||||
|
||||
services.gitea-actions-runner = {
|
||||
package = pkgs.forgejo-runner;
|
||||
instances.default = {
|
||||
enable = true;
|
||||
name = "${config.networking.hostName}-nix";
|
||||
inherit (cfg) url tokenFile;
|
||||
|
||||
labels = [ "host:host" ];
|
||||
|
||||
hostPackages = with pkgs; [
|
||||
bash
|
||||
coreutils
|
||||
curl
|
||||
gitMinimal
|
||||
gnused
|
||||
nix
|
||||
nodejs
|
||||
openssh
|
||||
deploy-rs
|
||||
];
|
||||
|
||||
settings = {
|
||||
log.level = "info";
|
||||
runner = {
|
||||
capacity = 1;
|
||||
envs = {
|
||||
NIX_CONFIG = "extra-experimental-features = nix-command flakes";
|
||||
NIX_REMOTE = "daemon";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
63
modules/nixos/forgejo/default.nix
Normal file
63
modules/nixos/forgejo/default.nix
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.forgejo;
|
||||
|
||||
inherit (cfg) settings;
|
||||
inherit (lib)
|
||||
getExe
|
||||
head
|
||||
mkDefault
|
||||
mkIf
|
||||
;
|
||||
in
|
||||
{
|
||||
config = mkIf cfg.enable {
|
||||
services.forgejo = {
|
||||
database.type = "postgres";
|
||||
lfs.enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = "git.${config.networking.domain}";
|
||||
PROTOCOL = "http";
|
||||
ROOT_URL = "https://${settings.server.DOMAIN}/";
|
||||
HTTP_ADDR = "0.0.0.0";
|
||||
HTTP_PORT = 3456;
|
||||
SSH_PORT = head config.services.openssh.ports;
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
};
|
||||
ui = {
|
||||
DEFAULT_THEME = "forgejo-dark";
|
||||
};
|
||||
actions = {
|
||||
ENABLED = true;
|
||||
};
|
||||
mailer = {
|
||||
ENABLED = mkDefault false;
|
||||
SMTP_ADDR = "mail.${config.networking.domain}";
|
||||
FROM = "git@${settings.server.DOMAIN}";
|
||||
USER = "git@${settings.server.DOMAIN}";
|
||||
};
|
||||
};
|
||||
secrets = {
|
||||
mailer.PASSWD = mkIf settings.mailer.ENABLED config.sops.secrets."forgejo/mail-pw".path;
|
||||
};
|
||||
};
|
||||
|
||||
environment.shellAliases = {
|
||||
forgejo = "sudo -u ${cfg.user} ${getExe cfg.package} --config ${cfg.stateDir}/custom/conf/app.ini";
|
||||
};
|
||||
|
||||
sops.secrets."forgejo/mail-pw" = mkIf settings.mailer.ENABLED {
|
||||
owner = cfg.user;
|
||||
group = cfg.group;
|
||||
mode = "0400";
|
||||
};
|
||||
};
|
||||
}
|
||||
78
modules/nixos/headplane/default.nix
Normal file
78
modules/nixos/headplane/default.nix
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.headplane;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
headscale = config.services.headscale;
|
||||
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
mkIf
|
||||
;
|
||||
|
||||
inherit (lib.utils)
|
||||
mkReverseProxyOption
|
||||
mkVirtualHost
|
||||
;
|
||||
in
|
||||
{
|
||||
imports = [ inputs.headplane.nixosModules.headplane ];
|
||||
|
||||
options.services.headplane = {
|
||||
reverseProxy = mkReverseProxyOption "Headplane" "hp";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
nixpkgs.overlays = [
|
||||
inputs.headplane.overlays.default
|
||||
];
|
||||
|
||||
services.headplane = {
|
||||
settings = {
|
||||
server = {
|
||||
host = mkDefault (if cfg.reverseProxy.enable then "127.0.0.1" else "0.0.0.0");
|
||||
port = mkDefault 3000;
|
||||
cookie_secret_path = config.sops.secrets."headplane/cookie_secret".path;
|
||||
};
|
||||
headscale = {
|
||||
url = "http://127.0.0.1:${toString headscale.port}";
|
||||
public_url = headscale.settings.server_url;
|
||||
config_path = "/etc/headscale/config.yaml";
|
||||
};
|
||||
integration.agent = {
|
||||
enabled = mkDefault true;
|
||||
pre_authkey_path = config.sops.secrets."headplane/agent_pre_authkey".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = mkVirtualHost {
|
||||
port = cfg.settings.server.port;
|
||||
ssl = cfg.reverseProxy.forceSSL;
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets =
|
||||
let
|
||||
owner = headscale.user;
|
||||
group = headscale.group;
|
||||
mode = "0400";
|
||||
in
|
||||
{
|
||||
"headplane/cookie_secret" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
"headplane/agent_pre_authkey" = {
|
||||
inherit owner group mode;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
17
modules/nixos/headscale/acl.hujson
Normal file
17
modules/nixos/headscale/acl.hujson
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": ["*"],
|
||||
"dst": ["*:*"]
|
||||
}
|
||||
],
|
||||
"ssh": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": ["autogroup:member"],
|
||||
"dst": ["autogroup:member"],
|
||||
"users": ["autogroup:nonroot", "root"]
|
||||
}
|
||||
]
|
||||
}
|
||||
105
modules/nixos/headscale/default.nix
Normal file
105
modules/nixos/headscale/default.nix
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.headscale;
|
||||
domain = config.networking.domain;
|
||||
subdomain = cfg.reverseProxy.subdomain;
|
||||
fqdn = if (cfg.reverseProxy.enable && subdomain != "") then "${subdomain}.${domain}" else domain;
|
||||
acl = "headscale/acl.hujson";
|
||||
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
mkIf
|
||||
mkOption
|
||||
optional
|
||||
optionals
|
||||
types
|
||||
;
|
||||
|
||||
inherit (lib.utils)
|
||||
mkReverseProxyOption
|
||||
mkUrl
|
||||
mkVirtualHost
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.headscale = {
|
||||
reverseProxy = mkReverseProxyOption "Headscale" "hs";
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to automatically open firewall ports. TCP: 80, 443; UDP: 3478.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !cfg.settings.derp.server.enable || cfg.reverseProxy.forceSSL;
|
||||
message = "cryodev/nixos/headscale: DERP requires TLS";
|
||||
}
|
||||
{
|
||||
assertion = fqdn != cfg.settings.dns.base_domain;
|
||||
message = "cryodev/nixos/headscale: `settings.server_url` must be different from `settings.dns.base_domain`";
|
||||
}
|
||||
{
|
||||
assertion = !cfg.settings.dns.override_local_dns || cfg.settings.dns.nameservers.global != [ ];
|
||||
message = "cryodev/nixos/headscale: `settings.dns.nameservers.global` must be set when `settings.dns.override_local_dns` is true";
|
||||
}
|
||||
];
|
||||
|
||||
environment.etc.${acl} = {
|
||||
inherit (config.services.headscale) user group;
|
||||
source = ./acl.hujson;
|
||||
};
|
||||
|
||||
environment.shellAliases = {
|
||||
hs = "${cfg.package}/bin/headscale";
|
||||
};
|
||||
|
||||
services.headscale = {
|
||||
address = mkDefault (if cfg.reverseProxy.enable then "127.0.0.1" else "0.0.0.0");
|
||||
port = mkDefault 8077;
|
||||
settings = {
|
||||
policy.path = "/etc/${acl}";
|
||||
database.type = "sqlite"; # postgres is highly discouraged as it is only supported for legacy reasons
|
||||
server_url = mkUrl {
|
||||
inherit fqdn;
|
||||
ssl = with cfg.reverseProxy; enable && forceSSL;
|
||||
};
|
||||
derp.server.enable = cfg.reverseProxy.forceSSL;
|
||||
dns = {
|
||||
magic_dns = mkDefault true;
|
||||
base_domain = mkDefault "tail";
|
||||
search_domains = [ cfg.settings.dns.base_domain ];
|
||||
override_local_dns = mkDefault true;
|
||||
nameservers.global = optionals cfg.settings.dns.override_local_dns [
|
||||
"1.1.1.1"
|
||||
"1.0.0.1"
|
||||
"2606:4700:4700::1111"
|
||||
"2606:4700:4700::1001"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = mkIf cfg.reverseProxy.enable {
|
||||
"${fqdn}" = mkVirtualHost {
|
||||
inherit (cfg) address port;
|
||||
ssl = cfg.reverseProxy.forceSSL;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
];
|
||||
allowedUDPPorts = optional cfg.settings.derp.server.enable 3478;
|
||||
};
|
||||
};
|
||||
}
|
||||
104
modules/nixos/mailserver/default.nix
Normal file
104
modules/nixos/mailserver/default.nix
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
{
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.mailserver;
|
||||
domain = config.networking.domain;
|
||||
fqdn = "${cfg.subdomain}.${domain}";
|
||||
|
||||
inherit (lib)
|
||||
mapAttrs'
|
||||
mkDefault
|
||||
mkIf
|
||||
mkOption
|
||||
nameValuePair
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
imports = [ inputs.nixos-mailserver.nixosModules.mailserver ];
|
||||
|
||||
options.mailserver = {
|
||||
subdomain = mkOption {
|
||||
type = types.str;
|
||||
default = "mail";
|
||||
description = "Subdomain for rDNS";
|
||||
};
|
||||
accounts = mkOption {
|
||||
type = types.attrsOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
aliases = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "A list of aliases of this account. `@domain` will be appended automatically.";
|
||||
};
|
||||
sendOnly = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Specifies if the account should be a send-only account.";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
default = { };
|
||||
description = ''
|
||||
This options wraps `loginAccounts`.
|
||||
`loginAccounts.<attr-name>.name` will be automatically set to `<attr-name>@<domain>`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.subdomain != "";
|
||||
message = "cryodev/nixos/mailserver: config.mailserver.subdomain cannot be empty.";
|
||||
}
|
||||
];
|
||||
|
||||
mailserver = {
|
||||
fqdn = mkDefault fqdn;
|
||||
|
||||
domains = mkDefault [ domain ];
|
||||
certificateScheme = mkDefault "acme-nginx";
|
||||
stateVersion = mkDefault 1;
|
||||
|
||||
loginAccounts = mapAttrs' (
|
||||
user: accConf:
|
||||
nameValuePair "${user}@${domain}" {
|
||||
name = "${user}@${domain}";
|
||||
aliases = map (alias: "${alias}@${domain}") (accConf.aliases or [ ]);
|
||||
sendOnly = accConf.sendOnly;
|
||||
quota = mkDefault "5G";
|
||||
hashedPasswordFile = config.sops.secrets."mailserver/accounts/${user}".path;
|
||||
}
|
||||
) cfg.accounts;
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = mkDefault "postmaster@cryodev.xyz";
|
||||
defaults.webroot = mkDefault "/var/lib/acme/acme-challenge";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs.mailutils ];
|
||||
|
||||
sops = {
|
||||
secrets = mapAttrs' (
|
||||
user: _config:
|
||||
nameValuePair "mailserver/accounts/${user}" {
|
||||
restartUnits = [
|
||||
"postfix.service"
|
||||
"dovecot.service"
|
||||
];
|
||||
}
|
||||
) cfg.accounts;
|
||||
};
|
||||
};
|
||||
}
|
||||
72
modules/nixos/nginx/default.nix
Normal file
72
modules/nixos/nginx/default.nix
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.nginx;
|
||||
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
mkIf
|
||||
mkOption
|
||||
optional
|
||||
optionals
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.nginx = {
|
||||
forceSSL = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Force SSL for Nginx virtual host.";
|
||||
};
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to open the firewall for HTTP (and HTTPS if forceSSL is enabled).";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = optionals cfg.openFirewall (
|
||||
[
|
||||
80
|
||||
]
|
||||
++ optional cfg.forceSSL 443
|
||||
);
|
||||
|
||||
services.nginx = {
|
||||
recommendedOptimisation = mkDefault true;
|
||||
recommendedGzipSettings = mkDefault true;
|
||||
recommendedProxySettings = mkDefault true;
|
||||
recommendedTlsSettings = cfg.forceSSL;
|
||||
|
||||
commonHttpConfig = "access_log syslog:server=unix:/dev/log;";
|
||||
|
||||
resolver.addresses =
|
||||
let
|
||||
isIPv6 = addr: builtins.match ".*:.*:.*" addr != null;
|
||||
escapeIPv6 = addr: if isIPv6 addr then "[${addr}]" else addr;
|
||||
cloudflare = [
|
||||
"1.1.1.1"
|
||||
"2606:4700:4700::1111"
|
||||
];
|
||||
resolvers =
|
||||
if config.networking.nameservers == [ ] then cloudflare else config.networking.nameservers;
|
||||
in
|
||||
map escapeIPv6 resolvers;
|
||||
|
||||
sslDhparam = mkIf cfg.forceSSL config.security.dhparams.params.nginx.path;
|
||||
};
|
||||
|
||||
security.acme = mkIf cfg.forceSSL {
|
||||
acceptTerms = true;
|
||||
defaults.email = mkDefault "postmaster@${config.networking.domain}";
|
||||
defaults.webroot = mkDefault "/var/lib/acme/acme-challenge";
|
||||
};
|
||||
|
||||
security.dhparams = mkIf cfg.forceSSL {
|
||||
enable = true;
|
||||
params.nginx = { };
|
||||
};
|
||||
};
|
||||
}
|
||||
106
modules/nixos/nixvim/default.nix
Normal file
106
modules/nixos/nixvim/default.nix
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
inputs.nixvim.nixosModules.nixvim
|
||||
./plugins
|
||||
|
||||
./spellfiles.nix
|
||||
];
|
||||
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
enable = true; # Enable globally on NixOS
|
||||
defaultEditor = mkDefault true;
|
||||
viAlias = mkDefault true;
|
||||
vimAlias = mkDefault true;
|
||||
|
||||
# Removed home-manager specific options like 'enableMan' which is handled differently or not needed in system module context
|
||||
# Removed clipboard.providers.wl-copy as it's home-manager specific.
|
||||
# System-wide clipboard integration for headless servers is less critical but can be added if needed.
|
||||
|
||||
# vim.g.*
|
||||
globals = {
|
||||
mapleader = mkDefault " ";
|
||||
};
|
||||
|
||||
# vim.opt.*
|
||||
opts = {
|
||||
# behavior
|
||||
cursorline = mkDefault true; # highlights the line under the cursor
|
||||
mouse = mkDefault "a"; # enable mouse support
|
||||
nu = mkDefault true; # line numbers
|
||||
relativenumber = mkDefault true; # relative line numbers
|
||||
scrolloff = mkDefault 20; # keeps some context above/below cursor
|
||||
signcolumn = mkDefault "yes"; # reserve space for signs (e.g., GitGutter)
|
||||
undofile = mkDefault true; # persistent undo
|
||||
updatetime = mkDefault 500; # ms to wait for trigger an event (default 4000ms)
|
||||
wrap = mkDefault true; # wraps text if it exceeds the width of the window
|
||||
|
||||
# search
|
||||
ignorecase = mkDefault true; # ignore case in search patterns
|
||||
smartcase = mkDefault true; # smart case
|
||||
incsearch = mkDefault true; # incremental search
|
||||
hlsearch = mkDefault true; # highlight search
|
||||
|
||||
# windows
|
||||
splitbelow = mkDefault true; # new windows are created below current
|
||||
splitright = mkDefault true; # new windows are created to the right of current
|
||||
equalalways = mkDefault true; # window sizes are automatically updated.
|
||||
|
||||
# tabs
|
||||
expandtab = mkDefault true; # convert tabs into spaces
|
||||
shiftwidth = mkDefault 2; # number of spaces to use for each step of (auto)indent
|
||||
smartindent = mkDefault true; # smart autoindenting on new lines
|
||||
softtabstop = mkDefault 2; # number of spaces in tab when editing
|
||||
tabstop = mkDefault 2; # number of visual spaces per tab
|
||||
|
||||
# spell checking
|
||||
spell = mkDefault true;
|
||||
spelllang = mkDefault [
|
||||
"en_us"
|
||||
"de_20"
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
# vim.diagnostic.config.*
|
||||
diagnostic.settings = {
|
||||
virtual_text = {
|
||||
spacing = 4;
|
||||
prefix = "●";
|
||||
severity_sort = true;
|
||||
};
|
||||
signs = true;
|
||||
underline = true;
|
||||
update_in_insert = false;
|
||||
};
|
||||
|
||||
extraConfigLua = ''
|
||||
vim.cmd "set noshowmode" -- Hides "--INSERT--" mode indicator
|
||||
'';
|
||||
|
||||
keymaps = import ./keymaps.nix;
|
||||
};
|
||||
|
||||
environment = {
|
||||
variables = {
|
||||
EDITOR = mkIf cfg.enable "nvim";
|
||||
VISUAL = mkIf cfg.enable "nvim";
|
||||
};
|
||||
shellAliases = {
|
||||
v = mkIf cfg.enable "nvim";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
347
modules/nixos/nixvim/keymaps.nix
Normal file
347
modules/nixos/nixvim/keymaps.nix
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
[
|
||||
# cursor navigation
|
||||
{
|
||||
# scroll down, recenter
|
||||
key = "<C-d>";
|
||||
action = "<C-d>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# scroll up, recenter
|
||||
key = "<C-u>";
|
||||
action = "<C-u>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# searching
|
||||
{
|
||||
# center cursor after search next
|
||||
key = "n";
|
||||
action = "nzzzv";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# center cursor after search previous
|
||||
key = "N";
|
||||
action = "Nzzzv";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# ex command
|
||||
key = "<leader>pv";
|
||||
action = "<cmd>Ex<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# search and replace
|
||||
{
|
||||
# search and replace word under cursor
|
||||
key = "<leader>s";
|
||||
action = ":%s/<C-r><C-w>/<C-r><C-w>/gI<Left><Left><Left>";
|
||||
mode = "n";
|
||||
}
|
||||
# search and replace selected text
|
||||
{
|
||||
key = "<leader>s";
|
||||
action = "y:%s/<C-r>0/<C-r>0/gI<Left><Left><Left>";
|
||||
mode = "v";
|
||||
}
|
||||
|
||||
# clipboard operations
|
||||
{
|
||||
# copy to system clipboard in visual mode
|
||||
key = "<C-c>";
|
||||
action = ''"+y '';
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
# paste from system clipboard in visual mode
|
||||
key = "<C-v>";
|
||||
action = ''"+p '';
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
# yank to system clipboard
|
||||
key = "<leader>Y";
|
||||
action = "+Y";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# replace selected text with clipboard content
|
||||
key = "<leader>p";
|
||||
action = "_dP";
|
||||
mode = "x";
|
||||
}
|
||||
{
|
||||
# delete without copying to clipboard
|
||||
key = "<leader>d";
|
||||
action = "_d";
|
||||
mode = [
|
||||
"n"
|
||||
"v"
|
||||
];
|
||||
}
|
||||
|
||||
# line operations
|
||||
{
|
||||
# move lines down in visual mode
|
||||
key = "J";
|
||||
action = ":m '>+1<CR>gv=gv";
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
# move lines up in visual mode
|
||||
key = "K";
|
||||
action = ":m '<-2<CR>gv=gv";
|
||||
mode = "v";
|
||||
}
|
||||
{
|
||||
# join lines
|
||||
key = "J";
|
||||
action = "mzJ`z";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# quickfix
|
||||
{
|
||||
# Run make command
|
||||
key = "<leader>m";
|
||||
action = "<cmd>:make<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# previous quickfix item
|
||||
key = "<C-A-J>";
|
||||
action = "<cmd>cprev<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# next quickfix item
|
||||
key = "<C-A-K>";
|
||||
action = "<cmd>cnext<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# location list navigation
|
||||
{
|
||||
# previous location list item
|
||||
key = "<leader>j";
|
||||
action = "<cmd>lprev<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# next location list item
|
||||
key = "<leader>k";
|
||||
action = "<cmd>lnext<CR>zz";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# disabling keys
|
||||
{
|
||||
# disable the 'Q' key
|
||||
key = "Q";
|
||||
action = "<nop>";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# text selection
|
||||
{
|
||||
# select whole buffer
|
||||
key = "<C-a>";
|
||||
action = "ggVG";
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window operations
|
||||
{
|
||||
# focus next window
|
||||
key = "<C-j>";
|
||||
action = ":wincmd W<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# focus previous window
|
||||
key = "<C-k>";
|
||||
action = ":wincmd w<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window size adjustments
|
||||
{
|
||||
# increase window width
|
||||
key = "<C-l>";
|
||||
action = ":vertical resize +5<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# decrease window width
|
||||
key = "<C-h>";
|
||||
action = ":vertical resize -5<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window closing and opening
|
||||
{
|
||||
# close current window
|
||||
key = "<leader-S>c";
|
||||
action = ":q<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# new vertical split at $HOME
|
||||
key = "<leader>n";
|
||||
action = ":vsp $HOME<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# window split orientation toggling
|
||||
{
|
||||
# toggle split orientation
|
||||
key = "<leader>t";
|
||||
action = ":wincmd T<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# spell checking
|
||||
{
|
||||
# toggle spell checking
|
||||
key = "<leader>ss";
|
||||
action = ":setlocal spell!<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# switch to english spell checking
|
||||
key = "<leader>se";
|
||||
action = ":setlocal spelllang=en_us<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# switch to german spell checking
|
||||
key = "<leader>sg";
|
||||
action = ":setlocal spelllang=de_20<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# move to next misspelling
|
||||
key = "]s";
|
||||
action = "]szz";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# move to previous misspelling
|
||||
key = "[s";
|
||||
action = "[szz";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# correction suggestions for a misspelled word
|
||||
key = "z=";
|
||||
action = "z=";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# adding words to the dictionary
|
||||
key = "zg";
|
||||
action = "zg";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
# buffer navigation
|
||||
{
|
||||
# next buffer
|
||||
key = "<C-S-J>";
|
||||
action = ":bnext<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# previous buffer
|
||||
key = "<C-S-K>";
|
||||
action = ":bprevious<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
{
|
||||
# close current buffer
|
||||
key = "<leader>bd";
|
||||
action = ":bdelete<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
|
||||
{
|
||||
# apply code action
|
||||
key = "<leader>ca";
|
||||
action = ":lua vim.lsp.buf.code_action()<CR>";
|
||||
options = {
|
||||
noremap = true;
|
||||
silent = true;
|
||||
};
|
||||
mode = "n";
|
||||
}
|
||||
]
|
||||
54
modules/nixos/nixvim/plugins/cmp.nix
Normal file
54
modules/nixos/nixvim/plugins/cmp.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.cmp;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
programs.nixvim = {
|
||||
plugins = {
|
||||
cmp = {
|
||||
enable = mkDefault true;
|
||||
settings = {
|
||||
autoEnableSources = mkDefault true;
|
||||
experimental.ghost_text = mkDefault true;
|
||||
snippet.expand = mkDefault "luasnip";
|
||||
formatting.fields = mkDefault [
|
||||
"kind"
|
||||
"abbr"
|
||||
"menu"
|
||||
];
|
||||
sources = [
|
||||
{ name = "git"; }
|
||||
{ name = "nvim_lsp"; }
|
||||
{
|
||||
name = "buffer";
|
||||
option.get_bufnrs.__raw = "vim.api.nvim_list_bufs";
|
||||
keywordLength = 3;
|
||||
}
|
||||
{
|
||||
name = "path";
|
||||
keywordLength = 3;
|
||||
}
|
||||
{ name = "luasnip"; }
|
||||
];
|
||||
mapping = {
|
||||
"<C-Space>" = "cmp.mapping.complete()";
|
||||
"<C-d>" = "cmp.mapping.scroll_docs(-4)";
|
||||
"<C-e>" = "cmp.mapping.close()";
|
||||
"<C-f>" = "cmp.mapping.scroll_docs(4)";
|
||||
"<C-CR>" = "cmp.mapping.confirm({ select = true })";
|
||||
"<S-Tab>" = "cmp.mapping(cmp.mapping.select_prev_item(), {'i', 's'})";
|
||||
"<Tab>" = "cmp.mapping(cmp.mapping.select_next_item(), {'i', 's'})";
|
||||
};
|
||||
};
|
||||
};
|
||||
cmp-cmdline = mkIf plugin.enable { enable = mkDefault false; }; # autocomplete for cmdline
|
||||
cmp_luasnip = mkIf plugin.enable { enable = mkDefault true; };
|
||||
luasnip = mkIf plugin.enable { enable = mkDefault true; };
|
||||
cmp-treesitter = mkIf (plugin.enable && cfg.plugins.treesitter.enable) { enable = mkDefault true; };
|
||||
};
|
||||
};
|
||||
}
|
||||
18
modules/nixos/nixvim/plugins/default.nix
Normal file
18
modules/nixos/nixvim/plugins/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./cmp.nix
|
||||
./lsp.nix
|
||||
./lualine.nix
|
||||
./telescope.nix
|
||||
# ./treesitter.nix # HOTFIX: does not build
|
||||
./trouble.nix
|
||||
];
|
||||
|
||||
config.programs.nixvim.plugins = {
|
||||
markdown-preview.enable = lib.mkDefault true;
|
||||
# warning: Nixvim: `plugins.web-devicons` was enabled automatically because the following plugins are enabled. This behaviour is deprecated. Please explicitly define `plugins.web-devicons.enable`
|
||||
web-devicons.enable = true;
|
||||
};
|
||||
}
|
||||
69
modules/nixos/nixvim/plugins/lsp.nix
Normal file
69
modules/nixos/nixvim/plugins/lsp.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.lsp;
|
||||
|
||||
inherit (lib) mkDefault mkIf optional;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins = {
|
||||
lsp-format = mkIf plugin.enable { enable = mkDefault true; };
|
||||
|
||||
lsp = {
|
||||
enable = mkDefault true;
|
||||
postConfig = "";
|
||||
keymaps = {
|
||||
silent = mkDefault true;
|
||||
diagnostic = mkDefault {
|
||||
# Navigate in diagnostics
|
||||
"<leader>k" = "goto_prev";
|
||||
"<leader>j" = "goto_next";
|
||||
};
|
||||
|
||||
lspBuf = mkDefault {
|
||||
gd = "definition";
|
||||
gD = "references";
|
||||
gt = "type_definition";
|
||||
gi = "implementation";
|
||||
K = "hover";
|
||||
"<F2>" = "rename";
|
||||
};
|
||||
};
|
||||
|
||||
servers = {
|
||||
bashls.enable = mkDefault true;
|
||||
clangd.enable = mkDefault true;
|
||||
cssls.enable = mkDefault true;
|
||||
dockerls.enable = mkDefault true;
|
||||
gopls.enable = mkDefault true;
|
||||
html.enable = mkDefault true;
|
||||
jsonls.enable = mkDefault true;
|
||||
nixd.enable = mkDefault true;
|
||||
pyright.enable = mkDefault true;
|
||||
rust_analyzer = {
|
||||
enable = mkDefault true;
|
||||
installCargo = mkDefault true;
|
||||
installRustc = mkDefault true;
|
||||
settings.rustfmt.overrideCommand = mkDefault [
|
||||
"${pkgs.rustfmt}/bin/rustfmt --edition 2021" # --config tab_spaces=2"
|
||||
];
|
||||
};
|
||||
texlab.enable = mkDefault true;
|
||||
vhdl_ls.enable = mkDefault true;
|
||||
yamlls.enable = mkDefault true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home.packages = optional (cfg.enable && plugin.servers.nixd.enable) pkgs.nixfmt;
|
||||
};
|
||||
}
|
||||
18
modules/nixos/nixvim/plugins/lualine.nix
Normal file
18
modules/nixos/nixvim/plugins/lualine.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.lualine;
|
||||
|
||||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.lualine = {
|
||||
enable = mkDefault true;
|
||||
settings.options.icons_enabled = mkDefault false;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
52
modules/nixos/nixvim/plugins/telescope.nix
Normal file
52
modules/nixos/nixvim/plugins/telescope.nix
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.telescope;
|
||||
|
||||
inherit (lib) mkDefault optionals;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.telescope = {
|
||||
enable = mkDefault true;
|
||||
extensions = {
|
||||
file-browser.enable = mkDefault true;
|
||||
fzf-native.enable = mkDefault true;
|
||||
live-grep-args.enable = mkDefault true;
|
||||
manix.enable = mkDefault true;
|
||||
};
|
||||
keymaps = mkDefault {
|
||||
"<C-e>" = "file_browser";
|
||||
"<C-p>" = "git_files";
|
||||
"<leader>bl" = "buffers";
|
||||
"<leader>fd" = "diagnostics";
|
||||
"<leader>ff" = "find_files";
|
||||
"<leader>fg" = "live_grep";
|
||||
"<leader>fh" = "help_tags";
|
||||
"<leader>fm" = "man_pages";
|
||||
"<leader>fn" = "manix";
|
||||
"<leader>fo" = "oldfiles";
|
||||
"<space>fb" = "file_browser";
|
||||
};
|
||||
};
|
||||
keymaps = optionals plugin.enable [
|
||||
{
|
||||
key = "<C-f>";
|
||||
action = ":lua require('telescope').extensions.live_grep_args.live_grep_args()<CR>";
|
||||
mode = "n";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
home.packages = optionals plugin.enable [
|
||||
pkgs.ripgrep # for "live_grep"
|
||||
];
|
||||
};
|
||||
}
|
||||
42
modules/nixos/nixvim/plugins/treesitter.nix
Normal file
42
modules/nixos/nixvim/plugins/treesitter.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.treesitter;
|
||||
|
||||
cc = "${pkgs.gcc}/bin/gcc";
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.treesitter = {
|
||||
enable = mkDefault true;
|
||||
nixvimInjections = mkDefault true;
|
||||
settings = {
|
||||
folding.enable = mkDefault true;
|
||||
highlight.enable = mkDefault true;
|
||||
indent.enable = mkDefault true;
|
||||
};
|
||||
};
|
||||
plugins.treesitter-context = mkIf plugin.enable { enable = mkDefault true; };
|
||||
plugins.treesitter-textobjects = mkIf plugin.enable { enable = mkDefault true; };
|
||||
};
|
||||
|
||||
# Fix for: ERROR `cc` executable not found.
|
||||
home.sessionVariables = mkIf plugin.enable {
|
||||
CC = mkDefault cc;
|
||||
};
|
||||
|
||||
# Fix for: WARNING `tree-sitter` executable not found
|
||||
home.packages = mkIf plugin.enable [
|
||||
plugin.package
|
||||
];
|
||||
};
|
||||
}
|
||||
43
modules/nixos/nixvim/plugins/trouble.nix
Normal file
43
modules/nixos/nixvim/plugins/trouble.nix
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.nixvim;
|
||||
plugin = cfg.plugins.trouble;
|
||||
|
||||
inherit (lib) mkDefault mkIf;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
programs.nixvim = {
|
||||
plugins.trouble = {
|
||||
enable = mkDefault true;
|
||||
};
|
||||
keymaps = mkIf plugin.enable [
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>xq";
|
||||
action = "<CMD>Trouble qflist toggle<CR>";
|
||||
options = {
|
||||
desc = "Trouble quifick toggle";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>xl";
|
||||
action = "<CMD>Trouble loclist toggle<CR>";
|
||||
options = {
|
||||
desc = "Trouble loclist toggle";
|
||||
};
|
||||
}
|
||||
{
|
||||
mode = "n";
|
||||
key = "<leader>xx";
|
||||
action = "<CMD>Trouble diagnostics toggle<CR>";
|
||||
options = {
|
||||
desc = "Trouble diagnostics toggle";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
26
modules/nixos/nixvim/spellfiles.nix
Normal file
26
modules/nixos/nixvim/spellfiles.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
spellDir = config.xdg.dataHome + "/nvim/site/spell";
|
||||
baseUrl = "http://ftp.de.vim.org/runtime/spell";
|
||||
in
|
||||
{
|
||||
home.file = {
|
||||
de-spl = {
|
||||
enable = true;
|
||||
source = pkgs.fetchurl {
|
||||
url = baseUrl + "/de.utf-8.spl";
|
||||
sha256 = "sha256-c8cQfqM5hWzb6SHeuSpFk5xN5uucByYdobndGfaDo9E=";
|
||||
};
|
||||
target = spellDir + "/de.utf8.spl";
|
||||
};
|
||||
de-sug = {
|
||||
enable = true;
|
||||
source = pkgs.fetchurl {
|
||||
url = baseUrl + "/de.utf-8.sug";
|
||||
sha256 = "sha256-E9Ds+Shj2J72DNSopesqWhOg6Pm6jRxqvkerqFcUqUg=";
|
||||
};
|
||||
target = spellDir + "/de.utf8.sug";
|
||||
};
|
||||
};
|
||||
}
|
||||
69
modules/nixos/normalUsers/default.nix
Normal file
69
modules/nixos/normalUsers/default.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.normalUsers;
|
||||
|
||||
inherit (lib)
|
||||
attrNames
|
||||
genAttrs
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
options.normalUsers = mkOption {
|
||||
type = types.attrsOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
extraGroups = mkOption {
|
||||
type = (types.listOf types.str);
|
||||
default = [ ];
|
||||
description = "Extra groups for the user";
|
||||
example = [ "wheel" ];
|
||||
};
|
||||
shell = mkOption {
|
||||
type = types.path;
|
||||
default = pkgs.zsh;
|
||||
description = "Shell for the user";
|
||||
};
|
||||
initialPassword = mkOption {
|
||||
type = types.str;
|
||||
default = "changeme";
|
||||
description = "Initial password for the user";
|
||||
};
|
||||
sshKeyFiles = mkOption {
|
||||
type = (types.listOf types.path);
|
||||
default = [ ];
|
||||
description = "SSH key files for the user";
|
||||
example = [ "/path/to/id_rsa.pub" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
default = { };
|
||||
description = "Users to create. The usernames are the attribute names.";
|
||||
};
|
||||
|
||||
config = {
|
||||
# Create user groups
|
||||
users.groups = genAttrs (attrNames cfg) (userName: {
|
||||
name = userName;
|
||||
});
|
||||
|
||||
# Create users
|
||||
users.users = genAttrs (attrNames cfg) (userName: {
|
||||
name = userName;
|
||||
inherit (cfg.${userName}) extraGroups shell initialPassword;
|
||||
|
||||
isNormalUser = true;
|
||||
group = "${userName}";
|
||||
home = "/home/${userName}";
|
||||
openssh.authorizedKeys.keyFiles = cfg.${userName}.sshKeyFiles;
|
||||
});
|
||||
};
|
||||
}
|
||||
16
modules/nixos/openssh/default.nix
Normal file
16
modules/nixos/openssh/default.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{ lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
services.openssh = {
|
||||
enable = mkDefault true;
|
||||
ports = mkDefault [ 2299 ];
|
||||
openFirewall = mkDefault true;
|
||||
settings = {
|
||||
PermitRootLogin = mkDefault "no";
|
||||
PasswordAuthentication = mkDefault false;
|
||||
};
|
||||
};
|
||||
}
|
||||
21
modules/nixos/sops/default.nix
Normal file
21
modules/nixos/sops/default.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
secrets = "${toString inputs.self}/hosts/${config.networking.hostName}/secrets/secrets.yaml";
|
||||
in
|
||||
{
|
||||
imports = [ inputs.sops-nix.nixosModules.sops ];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
age
|
||||
sops
|
||||
];
|
||||
|
||||
sops.defaultSopsFile = lib.mkIf (builtins.pathExists secrets) (lib.mkDefault secrets);
|
||||
}
|
||||
50
modules/nixos/tailscale/default.nix
Normal file
50
modules/nixos/tailscale/default.nix
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.tailscale;
|
||||
|
||||
inherit (lib)
|
||||
mkIf
|
||||
mkOption
|
||||
optional
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.tailscale = {
|
||||
loginServer = mkOption {
|
||||
type = types.str;
|
||||
description = "The Tailscale login server to use.";
|
||||
};
|
||||
enableSSH = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable Tailscale SSH functionality.";
|
||||
};
|
||||
acceptDNS = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Tailscale's MagicDNS and custom DNS configuration.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
|
||||
extraSetFlags = optional cfg.enableSSH "--ssh" ++ optional cfg.acceptDNS "--accept-dns";
|
||||
extraUpFlags = [
|
||||
"--login-server=${cfg.loginServer}"
|
||||
]
|
||||
++ optional cfg.enableSSH "--ssh"
|
||||
++ optional cfg.acceptDNS "--accept-dns";
|
||||
};
|
||||
|
||||
environment.shellAliases = {
|
||||
ts = "${cfg.package}/bin/tailscale";
|
||||
};
|
||||
|
||||
networking.firewall.trustedInterfaces = [ cfg.interfaceName ];
|
||||
|
||||
sops.secrets."tailscale/auth-key" = { };
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue