Compare commits

...

49 commits

Author SHA1 Message Date
Bruno BELANYI 5563a1718f WIP: add notes for missing persistence/backup
Some checks failed
ci/woodpecker/push/check Pipeline failed
TODO:
* Look at for more inspiration https://github.com/nix-community/impermanence/pull/108
* Do home-manager
* Common files https://github.com/nix-community/impermanence/issues/10
2024-11-28 20:19:49 +00:00
Bruno BELANYI 8147670f48 nixos: services: quassel: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 5d60031018 nixos: services: pirate: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 235b7b7a02 nixos: services: monitoring: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI b5cb3ccbb7 nixos: services: nginx: persist SSL certificates 2024-11-28 20:19:49 +00:00
Bruno BELANYI 6ad3677621 nixos: services: transmission: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI dff50c1b56 nixos: services: sabnzbd: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI f5169f5fae nixos: services: rss-bridge: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 66c05a1388 nixos: services: podgrab: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 192482d816 nixos: services: nextcloud: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 28e9efd254 nixos: services: navidrome: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 88bb795cc5 nixos: services: lohr: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 7ce456d603 nixos: services: jellyfin: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 7a2c1eb473 nixos: services: indexers: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 1320cfbcb0 nixos: services: postgresql: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI d0da754a65 nixos: services: postgresql-backup: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 2fe4dc1c80 nixos: services: paperless: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI b891b6c131 nixos: services: matrix: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 04a6af9a89 nixos: services: forgejo: persist repositories 2024-11-28 20:19:49 +00:00
Bruno BELANYI d37139ee0f nixos: services: gitea: persist repositories 2024-11-28 20:19:49 +00:00
Bruno BELANYI 1510142e29 nixos: services: calibre-web: persist library 2024-11-28 20:19:49 +00:00
Bruno BELANYI 0013102716 nixos: services: blog: persist website data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 990ff82250 nixos: services: ssh-server: persist host keys 2024-11-28 20:19:49 +00:00
Bruno BELANYI b2190162c4 nixos: hardware: networking persist connections 2024-11-28 20:19:49 +00:00
Bruno BELANYI 7e568c29ce nixos: hardware: bluetooth: persist connections 2024-11-28 20:19:49 +00:00
Bruno BELANYI d0a7ec4d81 nixos: system: podman: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 828621041a nixos: system: docker: persist data 2024-11-28 20:19:49 +00:00
Bruno BELANYI 0f2109c4b0 WIP: nixos: system: add persist
This is the module that takes care of configuring impermanence at the
system level.

WIP:
    * address FIXMEs
    * activate home-manager persistence?
        * set `programs.fuse.userAllowOther = true;` ?
    * point `age` to persisted paths [1] ?
    * make sure all services and modules are persisted correctly...

[1]: b1d18d25b8
2024-11-28 20:19:22 +00:00
Bruno BELANYI 05fdbcdb76 flake: add 'impermanence' 2024-11-28 19:59:41 +00:00
Bruno BELANYI e03db8642a nixos: system: packages: remove 'wget'
All checks were successful
ci/woodpecker/push/check Pipeline was successful
2024-11-28 19:59:41 +00:00
Bruno BELANYI 9fc7d32481 home: tmux: add sloppy window switching bindings
All checks were successful
ci/woodpecker/push/check Pipeline was successful
Another set of bindings which were setup by `tmux-sensible`, that I want
to enable explicitly to avoid issues when it is disabled by default.
2024-11-28 18:39:10 +00:00
Bruno BELANYI b38658405a home: tmux: add binding to refresh configuration
Don't rely on `tmux-sensible` to set it up.
2024-11-28 18:39:09 +00:00
Bruno BELANYI da3c29bbaf home: xdg: add comment about 'tig'
To explain why I didn't modify it as part of my `$XDG_STATE_HOME`
migration in fbd3b70d61.
2024-11-28 12:07:52 +00:00
Bruno BELANYI 8b61af1ac3 home: xdg: remove 'gdb' directory
I have an actual module to configure `gdb`, and it uses
`$XDG_STATE_HOME` anyway...
2024-11-28 12:07:12 +00:00
Bruno BELANYI e8a41187e7 home: xdg: create 'HISTFILE' parent directory
In fbd3b70d61, I forgot to modify the
`.keep` file to be created in `$XDG_STATE_HOME/bash/`.
2024-11-28 12:06:03 +00:00
Bruno BELANYI 83da7ba9c8 home: tmux: explicitly disable mouse support
All checks were successful
ci/woodpecker/push/check Pipeline was successful
It's disabled by default, but make it explicit :-).
2024-11-28 11:24:34 +00:00
Bruno BELANYI f2168378fc home: direnv: lib: also watch '.python-version'
All checks were successful
ci/woodpecker/push/check Pipeline was successful
It's used by `uv` as a kind of configuration file, so watch it as well.
2024-11-27 15:12:10 +00:00
Bruno BELANYI e39fef275c nixos: services: paperless: use 'environmentFile'
All checks were successful
ci/woodpecker/push/check Pipeline was successful
That way I don't have to configure all services to make use of it.

Someday I'll find the will to add the `postgresql.service` dependency
upstream, truly removing the need to configure any service at all.
2024-11-27 12:05:41 +00:00
Bruno BELANYI fe49e47026 flake: bump inputs 2024-11-27 12:02:29 +00:00
Bruno BELANYI 6a5c4a627a nixos: services: pyload: add fail2ban jail
All checks were successful
ci/woodpecker/push/check Pipeline was successful
2024-11-20 21:06:17 +01:00
Bruno BELANYI 7f0cd6612e nixos: services: paperless: remove MKL work-around
Instead, rely on the upstream service's work-around [1].

This will reduce the amount of package builds I need to do when updating
my server...

[1]: https://github.com/NixOS/nixpkgs/pull/299008

This reverts commit e2ec4d3032.
2024-11-20 21:06:17 +01:00
Bruno BELANYI 2ffbc13513 flake: bump inputs 2024-11-20 21:06:17 +01:00
Bruno BELANYI 60050113bc nixos: services: nginx: modify example
All checks were successful
ci/woodpecker/push/check Pipeline was successful
Now that `websocketLocations` exists, it makes little sense to use
`proxyWebsockets` in an example, so use a different one.
2024-11-19 16:03:38 +00:00
Bruno BELANYI 6a1a35a384 nixos: services: migrate to 'websocketsLocations' 2024-11-19 16:03:38 +00:00
Bruno BELANYI e9d96138d5 nixos: services: nginx: add 'websocketsLocations'
This accounts for the overwhelming majority of my usage of
`extraConfig`.
2024-11-19 16:03:38 +00:00
Bruno BELANYI ae230b5df7 hosts: porthos: services: enable collabora
All checks were successful
ci/woodpecker/push/check Pipeline was successful
2024-11-19 15:58:48 +01:00
Bruno BELANYI 138d4d2bd9 nixos: services: nextcloud: add collabora
This needs to be configured through the "Nextcloud Office" app,
specifically the WOPI setting is important for security (I put both the
external IP, as well as `::1` and `127.0.0.1`).
2024-11-19 15:58:48 +01:00
Bruno BELANYI ab8a5daefe hosts: porthos: secrets: acme: use OVH API
All checks were successful
ci/woodpecker/push/check Pipeline was successful
I switched registrar, as OVH was ~4x cheaper.

This needs a small change to the module to both refer to OVH instead of
Gandi in the documentation, and make use of the correct API.

I also needed to disable the propagation check, as it looks like OVH is
slower than Gandi, and leads to spurious errors...
2024-11-14 22:19:35 +01:00
Bruno BELANYI 7b42368e2f hosts: nixos: porthos: services: remove tandoor
All checks were successful
ci/woodpecker/push/check Pipeline was successful
I fully transitioned to using Mealie instead.

This reverts commit 493636decb.
2024-11-11 11:45:11 +00:00
55 changed files with 427 additions and 88 deletions

View file

@ -94,11 +94,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1726560853, "lastModified": 1731533236,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -136,11 +136,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1730837930, "lastModified": 1732482255,
"narHash": "sha256-0kZL4m+bKBJUBQse0HanewWO0g8hDdCvBhudzxgehqc=", "narHash": "sha256-GUffLwzawz5WRVfWaWCg78n/HrBJrOG7QadFY6rtV8A=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "2f607e07f3ac7e53541120536708e824acccfaa8", "rev": "a9953635d7f34e7358d5189751110f87e3ac17da",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -150,13 +150,29 @@
"type": "github" "type": "github"
} }
}, },
"impermanence": {
"locked": {
"lastModified": 1697303681,
"narHash": "sha256-caJ0rXeagaih+xTgRduYtYKL1rZ9ylh06CIrt1w5B4g=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "0f317c2e9e56550ce12323eb39302d251618f5b5",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"repo": "impermanence",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1730785428, "lastModified": 1732521221,
"narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -168,11 +184,11 @@
}, },
"nur": { "nur": {
"locked": { "locked": {
"lastModified": 1730885145, "lastModified": 1732704680,
"narHash": "sha256-UPrBEY0No1O3ULb67xYjRh2r3u7MnZovfo1oYSPCIxI=", "narHash": "sha256-x3NlO2qzuobU9BrynzydX7X9oskJpysv7BI7DJ5cVSE=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NUR", "repo": "NUR",
"rev": "c0d8828600ef47d475e6ec33513bf9af6eb6b991", "rev": "31a30f0862fd8b5f88a6597382bb09197356b19e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -194,11 +210,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1730814269, "lastModified": 1732021966,
"narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", "narHash": "sha256-mnTbjpdqF0luOkou8ZFi2asa1N3AA2CchR/RqCNmsGE=",
"owner": "cachix", "owner": "cachix",
"repo": "pre-commit-hooks.nix", "repo": "pre-commit-hooks.nix",
"rev": "d70155fdc00df4628446352fc58adc640cd705c2", "rev": "3308484d1a443fc5bc92012435d79e80458fe43c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -214,6 +230,7 @@
"flake-parts": "flake-parts", "flake-parts": "flake-parts",
"futils": "futils", "futils": "futils",
"home-manager": "home-manager", "home-manager": "home-manager",
"impermanence": "impermanence",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nur": "nur", "nur": "nur",
"pre-commit-hooks": "pre-commit-hooks", "pre-commit-hooks": "pre-commit-hooks",

View file

@ -43,6 +43,13 @@
}; };
}; };
impermanence = {
type = "github";
owner = "nix-community";
repo = "impermanence";
ref = "master";
};
nixpkgs = { nixpkgs = {
type = "github"; type = "github";
owner = "NixOS"; owner = "NixOS";

View file

@ -1,8 +1,9 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 cKojmg bQFr9oAnbo1rI/MpUV8wQz/Xj7iZY4ZU+Swf0nSIQFw -> ssh-ed25519 cKojmg Ec0xt1uJTva8MxUdoTVX5m3uWaIiRlodf345FEM7Uzs
zama2XJ0gdvUlD2GHMhmZqHSxHe+dKSfXnHoWDcSw7Y aJIneWFJPB5HVeoUGp57agXih9YeZ6xMEbyQ+zJtWQY
-> ssh-ed25519 jPowng gitUwSKTNKWLSxnwa185O7x/u0ul93g8wPESdZaKRk8 -> ssh-ed25519 jPowng B5XotRgv7s/FUegGhceBj7EoukewNUOIFl4TFRQf1EQ
uvBIfAUkZp5sg6rfeEGvL5ZDV8m2uSEotW02kjPN3Hw PgGCBd/Pqwp7ayqi7okHBGF1SfFpwT4KlHJ/np6p2uQ
--- SZxe5f/CUZBvPQa2Sz/UBY3L68rMkIGGRuZPk7YE+Vg --- AeLgwGz6k3OABb53cXNaCU/sgI4FlU1s6p8PhAaFOlg
¾r ú&…¥‹{~v?¨}=Ä 1ÌÉCÔ¹ð¤ŽULfI1¸Hm»Ûòb}m” ÁÅ¡ìg•ß0¦¢–¤`X<16>G>\>¹8rŽz+ŠY ™¼`—Ê¢.JBUÏ!z¸Z50ú*õ¡ÙŸ¤×ÖÇ®I<C2AE>ôÔ]¹Ïå I
}+ ¿SQM[²]Œ±k MÒAàtŒÃmMë/£µLsü|Þ…m©CÀñiYC}ƒŽ‡çxŽ€ ĵ<18>¿oÒÛ°…g„®„ÒêÁ³Â¿Ÿt©nƒºãcz[»{
jçå&ÁõõNæ°Nÿo{õš½‚ -eP¾=L‰™ 6¦.SP:»e¶

View file

@ -95,6 +95,9 @@ in
nextcloud = { nextcloud = {
enable = true; enable = true;
passwordFile = secrets."nextcloud/password".path; passwordFile = secrets."nextcloud/password".path;
collabora = {
enable = true;
};
}; };
nix-cache = { nix-cache = {
enable = true; enable = true;
@ -149,11 +152,6 @@ in
}; };
# Because I still need to play sysadmin # Because I still need to play sysadmin
ssh-server.enable = true; ssh-server.enable = true;
# Recipe manager
tandoor-recipes = {
enable = true;
secretKeyFile = secrets."tandoor-recipes/secret-key".path;
};
# Torrent client and webui # Torrent client and webui
transmission = { transmission = {
enable = true; enable = true;

View file

@ -53,4 +53,5 @@ layout_uv() {
PATH_add "$VIRTUAL_ENV/bin" PATH_add "$VIRTUAL_ENV/bin"
watch_file pyproject.toml watch_file pyproject.toml
watch_file uv.lock watch_file uv.lock
watch_file .python-version
} }

View file

@ -47,6 +47,7 @@ in
clock24 = true; # I'm one of those heathens clock24 = true; # I'm one of those heathens
escapeTime = 0; # Let vim do its thing instead escapeTime = 0; # Let vim do its thing instead
historyLimit = 100000; # Bigger buffer historyLimit = 100000; # Bigger buffer
mouse = false; # I dislike mouse support
terminal = "tmux-256color"; # I want accurate termcap info terminal = "tmux-256color"; # I want accurate termcap info
plugins = with pkgs.tmuxPlugins; [ plugins = with pkgs.tmuxPlugins; [
@ -80,6 +81,13 @@ in
]; ];
extraConfig = '' extraConfig = ''
# Refresh configuration
bind-key -N "Source tmux.conf" R source-file ${config.xdg.configHome}/tmux/tmux.conf \; display-message "Sourced tmux.conf!"
# Accept sloppy Ctrl key when switching windows, on top of default mapping
bind-key -N "Select the previous window" C-p previous-window
bind-key -N "Select the next window" C-n next -window
# Better vim mode # Better vim mode
bind-key -T copy-mode-vi 'v' send -X begin-selection bind-key -T copy-mode-vi 'v' send -X begin-selection
${ ${

View file

@ -30,11 +30,10 @@ in
}; };
# A tidy home is a tidy mind # A tidy home is a tidy mind
dataFile = { dataFile = {
"bash/.keep".text = ""; "tig/.keep".text = ""; # `tig` uses `XDG_DATA_HOME` specifically...
"gdb/.keep".text = "";
"tig/.keep".text = "";
}; };
stateFile = { stateFile = {
"bash/.keep".text = "";
"python/.keep".text = ""; "python/.keep".text = "";
}; };
}; };

View file

@ -18,6 +18,13 @@ in
services.blueman.enable = true; services.blueman.enable = true;
} }
# Persist bluetooth files
{
my.system.persist.directories = [
"/var/lib/bluetooth"
];
}
# Support for additional bluetooth codecs # Support for additional bluetooth codecs
(lib.mkIf cfg.loadExtraCodecs { (lib.mkIf cfg.loadExtraCodecs {
hardware.pulseaudio = { hardware.pulseaudio = {

View file

@ -22,6 +22,11 @@ in
config = lib.mkMerge [ config = lib.mkMerge [
(lib.mkIf cfg.wireless.enable { (lib.mkIf cfg.wireless.enable {
networking.networkmanager.enable = true; networking.networkmanager.enable = true;
# Persist NetworkManager files
my.system.persist.directories = [
"/etc/NetworkManager/system-connections"
];
}) })
]; ];
} }

View file

@ -65,12 +65,12 @@ in
aria-rpc = { aria-rpc = {
port = cfg.rpcPort; port = cfg.rpcPort;
# Proxy websockets for RPC # Proxy websockets for RPC
extraConfig = { websocketsLocations = [ "/" ];
locations."/".proxyWebsockets = true;
};
}; };
}; };
# FIXME: persistence?
# NOTE: unfortunately aria2 does not log connection failures for fail2ban # NOTE: unfortunately aria2 does not log connection failures for fail2ban
}; };
} }

View file

@ -30,12 +30,12 @@ in
audiobookshelf = { audiobookshelf = {
inherit (cfg) port; inherit (cfg) port;
# Proxy websockets for RPC # Proxy websockets for RPC
extraConfig = { websocketsLocations = [ "/" ];
locations."/".proxyWebsockets = true;
};
}; };
}; };
# FIXME: persistence?
services.fail2ban.jails = { services.fail2ban.jails = {
audiobookshelf = '' audiobookshelf = ''
enabled = true enabled = true

View file

@ -41,5 +41,12 @@ in
# Those are all subdomains, no problem # Those are all subdomains, no problem
my.services.nginx.virtualHosts = hostsInfo; my.services.nginx.virtualHosts = hostsInfo;
my.system.persist.directories = [
"/var/www/blog"
"/var/www/cv"
"/var/www/dev"
"/var/www/key"
];
}; };
} }

View file

@ -53,6 +53,11 @@ in
]; ];
}; };
my.system.persist.directories = [
"/var/lib/${config.services.calibre-web.dataDir}"
cfg.libraryPath
];
services.fail2ban.jails = { services.fail2ban.jails = {
calibre-web = '' calibre-web = ''
enabled = true enabled = true

View file

@ -39,5 +39,7 @@ in
extraGroups = [ "docker" ]; # Give access to the daemon extraGroups = [ "docker" ]; # Give access to the daemon
}; };
users.groups.drone-runner-docker = { }; users.groups.drone-runner-docker = { };
# FIXME: persistence?
}; };
} }

View file

@ -63,5 +63,7 @@ in
group = "drone-runner-exec"; group = "drone-runner-exec";
}; };
users.groups.drone-runner-exec = { }; users.groups.drone-runner-exec = { };
# FIXME: persistence?
}; };
} }

View file

@ -50,5 +50,7 @@ in
inherit (cfg) port; inherit (cfg) port;
}; };
}; };
# FIXME: persistence?
}; };
} }

View file

@ -33,5 +33,7 @@ in
bantime = "10m"; bantime = "10m";
}; };
}; };
# FIXME: persistence?
}; };
} }

View file

@ -28,6 +28,8 @@ in
}; };
}; };
# FIXME: persistence?
# NOTE: unfortunately flood does not log connection failures for fail2ban # NOTE: unfortunately flood does not log connection failures for fail2ban
}; };
} }

View file

@ -147,6 +147,11 @@ in
]; ];
}; };
my.system.persist.directories = [
config.services.forgejo.lfs.contentDir
config.services.forgejo.repositoryRoot
];
services.fail2ban.jails = { services.fail2ban.jails = {
forgejo = '' forgejo = ''
enabled = true enabled = true

View file

@ -131,6 +131,11 @@ in
]; ];
}; };
my.system.persist.directories = [
config.services.gitea.lfs.contentDir
config.services.gitea.repositoryRoot
];
services.fail2ban.jails = { services.fail2ban.jails = {
gitea = '' gitea = ''
enabled = true enabled = true

View file

@ -37,6 +37,9 @@ in
useACMEHost = config.networking.domain; useACMEHost = config.networking.domain;
}; };
# FIXME: backup
# FIXME: persistence
# NOTE: unfortunately grocy does not log connection failures for fail2ban # NOTE: unfortunately grocy does not log connection failures for fail2ban
}; };
} }

View file

@ -33,6 +33,10 @@ in
port = jackettPort; port = jackettPort;
}; };
}; };
my.system.persist.directories = [
config.services.jackett.dataDir
];
}) })
(lib.mkIf cfg.nzbhydra.enable { (lib.mkIf cfg.nzbhydra.enable {
@ -45,6 +49,10 @@ in
port = nzbhydraPort; port = nzbhydraPort;
}; };
}; };
my.system.persist.directories = [
config.services.nzbhydra2.dataDir
];
}) })
(lib.mkIf cfg.prowlarr.enable { (lib.mkIf cfg.prowlarr.enable {
@ -58,6 +66,10 @@ in
}; };
}; };
my.system.persist.directories = [
"/var/lib/${config.systemd.services.prowlarr.serviceConfig.StateDirectory}"
];
services.fail2ban.jails = { services.fail2ban.jails = {
prowlarr = '' prowlarr = ''
enabled = true enabled = true

View file

@ -27,21 +27,21 @@ in
my.services.nginx.virtualHosts = { my.services.nginx.virtualHosts = {
jellyfin = { jellyfin = {
port = 8096; port = 8096;
websocketsLocations = [ "/socket" ];
extraConfig = { extraConfig = {
locations."/" = { locations."/" = {
extraConfig = '' extraConfig = ''
proxy_buffering off; proxy_buffering off;
''; '';
}; };
# Too bad for the repetition...
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096/";
proxyWebsockets = true;
};
}; };
}; };
}; };
my.system.persist.directories = [
"/var/lib/${config.systemd.services.jellyfin.serviceConfig.StateDirectory}"
];
services.fail2ban.jails = { services.fail2ban.jails = {
jellyfin = '' jellyfin = ''
enabled = true enabled = true

View file

@ -36,6 +36,8 @@ in
}; };
}; };
# FIXME: persistence?
services.fail2ban.jails = { services.fail2ban.jails = {
komga = '' komga = ''
enabled = true enabled = true

View file

@ -107,5 +107,9 @@ in
}; };
}; };
}; };
my.system.persist.directories = [
"/var/lib/${config.systemd.services.lohr.serviceConfig.StateDirectory}"
];
}; };
} }

View file

@ -214,5 +214,9 @@ in
config.services.matrix-synapse.dataDir config.services.matrix-synapse.dataDir
]; ];
}; };
my.system.persist.directories = [
config.services.matrix-synapse.dataDir
];
}; };
} }

View file

@ -72,6 +72,9 @@ in
}; };
}; };
# FIXME: backup
# FIXME: persistence
services.fail2ban.jails = { services.fail2ban.jails = {
mealie = '' mealie = ''
enabled = true enabled = true

View file

@ -49,6 +49,9 @@ in
}; };
}; };
# FIXME: backup
# FIXME: persistence
services.fail2ban.jails = { services.fail2ban.jails = {
miniflux = '' miniflux = ''
enabled = true enabled = true

View file

@ -130,5 +130,10 @@ in
inherit (cfg.grafana) port; inherit (cfg.grafana) port;
}; };
}; };
my.system.persist.directories = [
config.services.grafana.dataDir
"/var/lib/${config.services.prometheus.stateDir}"
];
}; };
} }

View file

@ -53,6 +53,10 @@ in
}; };
}; };
my.system.persist.directories = [
"/var/lib/${config.systemd.services.navidrome.serviceConfig.StateDirectory}"
];
services.fail2ban.jails = { services.fail2ban.jails = {
navidrome = '' navidrome = ''
enabled = true enabled = true

View file

@ -0,0 +1,52 @@
# Document editor with Nextcloud
{ config, lib, ... }:
let
cfg = config.my.services.nextcloud.collabora;
in
{
options.my.services.nextcloud.collabora = with lib; {
enable = mkEnableOption "Collabora integration";
port = mkOption {
type = types.port;
default = 9980;
example = 8080;
description = "Internal port for API";
};
};
config = lib.mkIf cfg.enable {
services.collabora-online = {
enable = true;
inherit (cfg) port;
aliasGroups = [
{
host = "https://collabora.${config.networking.domain}";
# Allow using from nextcloud
aliases = [ "https://${config.services.nextcloud.hostName}" ];
}
];
settings = {
# Rely on reverse proxy for SSL
ssl = {
enable = false;
termination = true;
};
};
};
my.services.nginx.virtualHosts = {
collabora = {
inherit (cfg) port;
websocketsLocations = [
"~ ^/cool/(.*)/ws$"
"^~ /cool/adminws"
];
};
};
# FIXME: persistence?
};
}

View file

@ -4,6 +4,10 @@ let
cfg = config.my.services.nextcloud; cfg = config.my.services.nextcloud;
in in
{ {
imports = [
./collabora.nix
];
options.my.services.nextcloud = with lib; { options.my.services.nextcloud = with lib; {
enable = mkEnableOption "Nextcloud"; enable = mkEnableOption "Nextcloud";
maxSize = mkOption { maxSize = mkOption {
@ -88,6 +92,11 @@ in
]; ];
}; };
my.system.persist.directories = [
config.services.nextcloud.home
config.services.nextcloud.datadir
];
services.fail2ban.jails = { services.fail2ban.jails = {
nextcloud = '' nextcloud = ''
enabled = true enabled = true

View file

@ -17,6 +17,16 @@ let
''; '';
}; };
websocketsLocations = mkOption {
type = with types; listOf str;
default = [ ];
example = [ "/socket" ];
description = ''
Which locations on this virtual host should be configured for
websockets.
'';
};
port = mkOption { port = mkOption {
type = with types; nullOr port; type = with types; nullOr port;
default = null; default = null;
@ -60,10 +70,13 @@ let
extraConfig = mkOption { extraConfig = mkOption {
type = types.attrs; # FIXME: forward type of virtualHosts type = types.attrs; # FIXME: forward type of virtualHosts
example = { example = {
locations."/socket" = { extraConfig = ''
proxyPass = "http://127.0.0.1:8096/"; add_header X-Clacks-Overhead "GNU Terry Pratchett";
proxyWebsockets = true; '';
};
locations."/".extraConfig = ''
client_max_body_size 1G;
'';
}; };
default = { }; default = { };
description = '' description = ''
@ -86,7 +99,7 @@ in
type = types.str; type = types.str;
example = "/var/lib/acme/creds.env"; example = "/var/lib/acme/creds.env";
description = '' description = ''
Gandi API key file as an 'EnvironmentFile' (see `systemd.exec(5)`) OVH API key file as an 'EnvironmentFile' (see `systemd.exec(5)`)
''; '';
}; };
}; };
@ -108,12 +121,7 @@ in
}; };
jellyfin = { jellyfin = {
port = 8096; port = 8096;
extraConfig = { websocketsLocations = [ "/socket" ];
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096/";
proxyWebsockets = true;
};
};
}; };
}; };
description = '' description = ''
@ -195,6 +203,19 @@ in
} configured. } configured.
''; '';
})) }))
++ (lib.flip lib.mapAttrsToList cfg.virtualHosts (_: { subdomain, ... } @ args:
let
proxyPass = [ "port" "socket" ];
proxyPassUsed = lib.any (v: args.${v} != null) proxyPass;
in
{
assertion = args.websocketsLocations != [ ] -> proxyPassUsed;
message = ''
Subdomain '${subdomain}' can only use 'websocketsLocations' with one of ${
lib.concatStringsSep ", " (builtins.map (v: "'${v}'") proxyPass)
}.
'';
}))
++ ( ++ (
let let
ports = lib.my.mapFilter ports = lib.my.mapFilter
@ -241,6 +262,14 @@ in
virtualHosts = virtualHosts =
let let
domain = config.networking.domain; domain = config.networking.domain;
mkProxyPass = { websocketsLocations, ... }: proxyPass:
let
websockets = lib.genAttrs websocketsLocations (_: {
inherit proxyPass;
proxyWebsockets = true;
});
in
{ "/" = { inherit proxyPass; }; } // websockets;
mkVHost = ({ subdomain, ... } @ args: lib.nameValuePair mkVHost = ({ subdomain, ... } @ args: lib.nameValuePair
"${subdomain}.${domain}" "${subdomain}.${domain}"
(lib.my.recursiveMerge [ (lib.my.recursiveMerge [
@ -251,8 +280,7 @@ in
} }
# Proxy to port # Proxy to port
(lib.optionalAttrs (args.port != null) { (lib.optionalAttrs (args.port != null) {
locations."/".proxyPass = locations = mkProxyPass args "http://127.0.0.1:${toString args.port}";
"http://127.0.0.1:${toString args.port}";
}) })
# Serve filesystem content # Serve filesystem content
(lib.optionalAttrs (args.root != null) { (lib.optionalAttrs (args.root != null) {
@ -260,8 +288,7 @@ in
}) })
# Serve to UNIX socket # Serve to UNIX socket
(lib.optionalAttrs (args.socket != null) { (lib.optionalAttrs (args.socket != null) {
locations."/".proxyPass = locations = mkProxyPass args "http://unix:${args.socket}";
"http://unix:${args.socket}";
}) })
# Redirect to a different domain # Redirect to a different domain
(lib.optionalAttrs (args.redirect != null) { (lib.optionalAttrs (args.redirect != null) {
@ -281,6 +308,7 @@ in
locations."/" = { locations."/" = {
extraConfig = extraConfig =
# FIXME: check that X-User is dropped otherwise
(args.extraConfig.locations."/".extraConfig or "") + '' (args.extraConfig.locations."/".extraConfig or "") + ''
# Use SSO # Use SSO
auth_request /sso-auth; auth_request /sso-auth;
@ -414,7 +442,8 @@ in
{ {
"${domain}" = { "${domain}" = {
extraDomainNames = [ "*.${domain}" ]; extraDomainNames = [ "*.${domain}" ];
dnsProvider = "gandiv5"; dnsProvider = "ovh";
dnsPropagationCheck = false; # OVH is slow
inherit (cfg.acme) credentialsFile; inherit (cfg.acme) credentialsFile;
}; };
}; };
@ -457,5 +486,9 @@ in
} }
]; ];
}; };
my.system.persist.directories = [
config.users.user.acme.home
];
}; };
} }

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, ... }:
let let
cfg = config.my.services.paperless; cfg = config.my.services.paperless;
in in
@ -80,50 +80,34 @@ in
# Misc # Misc
PAPERLESS_TIME_ZONE = config.time.timeZone; PAPERLESS_TIME_ZONE = config.time.timeZone;
PAPERLESS_ADMIN_USER = cfg.username; PAPERLESS_ADMIN_USER = cfg.username;
# Fix classifier hangs
LD_LIBRARY_PATH = "${lib.getLib pkgs.mkl}/lib";
}; };
# Admin password # Admin password
passwordFile = cfg.passwordFile; passwordFile = cfg.passwordFile;
# Secret key
environmentFile = cfg.secretKeyFile;
}; };
systemd.services = { systemd.services = {
paperless-scheduler = { paperless-scheduler = {
requires = [ "postgresql.service" ]; requires = [ "postgresql.service" ];
after = [ "postgresql.service" ]; after = [ "postgresql.service" ];
serviceConfig = {
EnvironmentFile = cfg.secretKeyFile;
};
}; };
paperless-consumer = { paperless-consumer = {
requires = [ "postgresql.service" ]; requires = [ "postgresql.service" ];
after = [ "postgresql.service" ]; after = [ "postgresql.service" ];
serviceConfig = {
EnvironmentFile = cfg.secretKeyFile;
};
}; };
paperless-web = { paperless-web = {
requires = [ "postgresql.service" ]; requires = [ "postgresql.service" ];
after = [ "postgresql.service" ]; after = [ "postgresql.service" ];
serviceConfig = {
EnvironmentFile = cfg.secretKeyFile;
};
}; };
paperless-task-queue = { paperless-task-queue = {
requires = [ "postgresql.service" ]; requires = [ "postgresql.service" ];
after = [ "postgresql.service" ]; after = [ "postgresql.service" ];
serviceConfig = {
EnvironmentFile = cfg.secretKeyFile;
};
}; };
}; };
@ -152,11 +136,7 @@ in
sso = { sso = {
enable = true; enable = true;
}; };
websocketsLocations = [ "/" ];
# Enable websockets on root
extraConfig = {
locations."/".proxyWebsockets = true;
};
}; };
}; };
@ -166,5 +146,10 @@ in
config.services.paperless.mediaDir config.services.paperless.mediaDir
]; ];
}; };
my.system.persist.directories = [
config.services.paperless-ng.dataDir
config.services.paperless-ng.mediaDir
];
}; };
} }

View file

@ -54,6 +54,8 @@ in
}; };
}; };
# FIXME: persistence?
services.fail2ban.jails = { services.fail2ban.jails = {
stirling-pdf = '' stirling-pdf = ''
enabled = true enabled = true

View file

@ -51,5 +51,10 @@ in
inherit (cfg) port; inherit (cfg) port;
}; };
}; };
my.system.persist.directories = [
config.systemd.services.podgrab.environment.CONFIG
config.systemd.services.podgrab.environment.DATA
];
}; };
} }

View file

@ -24,5 +24,9 @@ in
(config.services.postgresqlBackup.location + "/*.prev.sql.gz") (config.services.postgresqlBackup.location + "/*.prev.sql.gz")
]; ];
}; };
my.system.persist.directories = [
config.services.postgresqlBackup.location
];
}; };
} }

View file

@ -18,6 +18,13 @@ in
}; };
}) })
# Only persist directory if the actual service is enabled
(lib.mkIf config.services.postgresql.enable {
my.system.persist.directories = [
config.services.postgresql.dataDir
];
})
# Taken from the manual # Taken from the manual
(lib.mkIf cfg.upgradeScript { (lib.mkIf cfg.upgradeScript {
environment.systemPackages = environment.systemPackages =

View file

@ -53,6 +53,23 @@ in
}; };
}; };
# FIXME: fail2ban # FIXME: backup
# FIXME: persistence
services.fail2ban.jails = {
pyload = ''
enabled = true
filter = pyload
port = http,https
'';
};
environment.etc = {
"fail2ban/filter.d/pyload.conf".text = ''
[Definition]
failregex = ^.*Login failed for user '<F-USER>.*</F-USER>' \[CLIENT: <HOST>\]$
journalmatch = _SYSTEMD_UNIT=pyload.service
'';
};
}; };
} }

View file

@ -46,5 +46,9 @@ in
# Because Quassel does not use the socket, I simply trust its connection # Because Quassel does not use the socket, I simply trust its connection
authentication = "host quassel quassel localhost trust"; authentication = "host quassel quassel localhost trust";
}; };
my.system.persist.directories = [
config.services.quassel.dataDir
];
}; };
} }

View file

@ -22,5 +22,9 @@ in
forceSSL = true; forceSSL = true;
useACMEHost = config.networking.domain; useACMEHost = config.networking.domain;
}; };
my.system.persist.directories = [
config.services.rss-bridge.dataDir
];
}; };
} }

View file

@ -24,6 +24,10 @@ in
}; };
}; };
my.system.persist.files = [
config.services.sabnzbd.configFile
];
services.fail2ban.jails = { services.fail2ban.jails = {
sabnzbd = '' sabnzbd = ''
enabled = true enabled = true

View file

@ -19,6 +19,11 @@ let
enable = true; enable = true;
group = "media"; group = "media";
}; };
# Thankfully those old style services all define users with homes
my.system.persist.directories = [
config.users.user.${service}.home
];
}; };
mkRedirection = service: { mkRedirection = service: {

View file

@ -20,6 +20,13 @@ in
}; };
}; };
# Persist SSH keys
my.system.persist.files =
let
pubAndPrivKey = key: [ key.path "${key.path}.pub" ];
in
lib.concatMap pubAndPrivKey systemConfig.services.openssh.hostKeys;
# Opens the relevant UDP ports. # Opens the relevant UDP ports.
programs.mosh.enable = true; programs.mosh.enable = true;
}; };

View file

@ -83,6 +83,9 @@ in
}; };
}; };
# FIXME: backup
# FIXME: persistence
# NOTE: unfortunately tandoor-recipes does not log connection failures for fail2ban # NOTE: unfortunately tandoor-recipes does not log connection failures for fail2ban
}; };
} }

View file

@ -91,6 +91,10 @@ in
allowedUDPPorts = [ cfg.peerPort ]; allowedUDPPorts = [ cfg.peerPort ];
}; };
my.system.persist.directories = [
config.services.transmission.home
];
# NOTE: unfortunately transmission does not log connection failures for fail2ban # NOTE: unfortunately transmission does not log connection failures for fail2ban
}; };
} }

View file

@ -100,6 +100,8 @@ in
]; ];
}; };
# FIXME: persistence
# NOTE: unfortunately vikunja does not log connection failures for fail2ban # NOTE: unfortunately vikunja does not log connection failures for fail2ban
}; };
} }

View file

@ -38,5 +38,7 @@ in
]; ];
}; };
}; };
# FIXME: persistence?
}; };
} }

View file

@ -62,5 +62,7 @@ in
]; ];
}; };
}; };
# FIXME: persistence?
}; };
} }

View file

@ -61,5 +61,7 @@ in
port = cfg.rpcPort; port = cfg.rpcPort;
}; };
}; };
# FIXME: persistence
}; };
} }

View file

@ -9,6 +9,7 @@
./language ./language
./nix ./nix
./packages ./packages
./persist
./podman ./podman
./polkit ./polkit
./printing ./printing

View file

@ -23,5 +23,9 @@ in
]; ];
}; };
}; };
my.system.persist.directories = [
"/var/lib/docker"
];
}; };
} }

View file

@ -1,5 +1,5 @@
# Common packages # Common packages
{ config, lib, pkgs, ... }: { config, lib, ... }:
let let
cfg = config.my.system.packages; cfg = config.my.system.packages;
in in
@ -13,10 +13,6 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [
wget
];
programs = { programs = {
vim = { vim = {
enable = true; enable = true;

View file

@ -0,0 +1,66 @@
# Ephemeral root configuration
{ config, inputs, lib, ... }:
let
cfg = config.my.system.persist;
in
{
imports = [
inputs.impermanence.nixosModules.impermanence
];
options.my.system.persist = with lib; {
enable = mkEnableOption "stateless system configuration";
mountPoint = lib.mkOption {
type = types.str;
default = "/persistent";
example = "/etc/nix/persist";
description = ''
Which mount point should be used to persist this system's files and
directories.
'';
};
files = lib.mkOption {
type = with types; listOf str;
default = [ ];
example = [
"/etc/nix/id_rsa"
];
description = ''
Additional files in the root to link to persistent storage.
'';
};
directories = lib.mkOption {
type = with types; listOf str;
default = [ ];
example = [
"/var/lib/libvirt"
];
description = ''
Additional directories in the root to link to persistent storage.
'';
};
};
config = lib.mkIf cfg.enable {
environment.persistence."${cfg.mountPoint}" = {
files = [
"/etc/machine-id" # Machine-specific ID
"/etc/adjtime" # Clock drift factor and offsets
]
++ cfg.files
;
directories = [
"/etc/nixos" # In case it's storage directory of our configuration
"/var/log" # Logs
"/var/lib/nixos" # UID/GID maps
"/var/lib/systemd/coredump" # Coredumps
]
++ cfg.directories
;
};
};
}

View file

@ -44,5 +44,9 @@ in
]; ];
}; };
}; };
my.system.persist.directories = [
"/var/lib/containers"
];
}; };
} }