migrate to clan
This commit is contained in:
21
machines/genepi/acme.nix
Normal file
21
machines/genepi/acme.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "admin@rpqt.fr";
|
||||
};
|
||||
|
||||
age.secrets.gandi.file = ../../secrets/gandi.age;
|
||||
|
||||
security.acme = {
|
||||
certs."home.rpqt.fr" = {
|
||||
group = config.services.nginx.group;
|
||||
|
||||
domain = "home.rpqt.fr";
|
||||
extraDomainNames = [ "*.home.rpqt.fr" ];
|
||||
dnsProvider = "gandiv5";
|
||||
dnsPropagationCheck = true;
|
||||
environmentFile = config.age.secrets.gandi.path;
|
||||
};
|
||||
};
|
||||
}
|
||||
19
machines/genepi/boot.nix
Normal file
19
machines/genepi/boot.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"usbhid"
|
||||
"usb_storage"
|
||||
];
|
||||
|
||||
boot.loader = {
|
||||
grub.enable = false;
|
||||
generic-extlinux-compatible.enable = true;
|
||||
};
|
||||
|
||||
boot.supportedFilesystems = [
|
||||
"btrfs"
|
||||
"vfat"
|
||||
];
|
||||
}
|
||||
11
machines/genepi/builder.nix
Normal file
11
machines/genepi/builder.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ keys, ... }:
|
||||
{
|
||||
imports = [
|
||||
../../modules/remote-builder.nix
|
||||
];
|
||||
|
||||
roles.remote-builder = {
|
||||
enable = true;
|
||||
authorizedKeys = [ keys.hosts.haze ];
|
||||
};
|
||||
}
|
||||
47
machines/genepi/configuration.nix
Normal file
47
machines/genepi/configuration.nix
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
inputs.agenix.nixosModules.default
|
||||
inputs.impermanence.nixosModules.impermanence
|
||||
./acme.nix
|
||||
./boot.nix
|
||||
./builder.nix
|
||||
./dns.nix
|
||||
./freshrss.nix
|
||||
./glance.nix
|
||||
./homeassistant.nix
|
||||
# ./immich.nix
|
||||
./monitoring
|
||||
./mpd.nix
|
||||
./network.nix
|
||||
./nginx.nix
|
||||
./persistence.nix
|
||||
./syncthing.nix
|
||||
./taskchampion.nix
|
||||
|
||||
../../system
|
||||
../../modules/borgbackup.nix
|
||||
|
||||
inputs.clan-core.clanModules.state-version
|
||||
inputs.clan-core.clanModules.trusted-nix-caches
|
||||
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.users.rpqt = ./home.nix;
|
||||
}
|
||||
];
|
||||
|
||||
networking.hostName = "genepi";
|
||||
clan.core.networking.targetHost = "root@genepi.local";
|
||||
|
||||
nix.gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 30d";
|
||||
};
|
||||
}
|
||||
86
machines/genepi/disko.nix
Normal file
86
machines/genepi/disko.nix
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
disko.devices.disk.main = {
|
||||
type = "disk";
|
||||
device = "/dev/disk/by-id/ata-WD_Green_M.2_2280_480GB_2251E6411147";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
priority = 1;
|
||||
name = "ESP";
|
||||
start = "1M";
|
||||
end = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
root = {
|
||||
end = "-4G";
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [
|
||||
"-L"
|
||||
"nixos"
|
||||
"-f" # Override existing partition
|
||||
];
|
||||
subvolumes = {
|
||||
"/root" = {
|
||||
mountpoint = "/";
|
||||
mountOptions = [
|
||||
"subvol=root"
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"/home" = {
|
||||
mountpoint = "/home";
|
||||
mountOptions = [
|
||||
"subvol=home"
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"/nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [
|
||||
"subvol=nix"
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"/persist" = {
|
||||
mountpoint = "/persist";
|
||||
mountOptions = [
|
||||
"subvol=persist"
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"/log" = {
|
||||
mountpoint = "/var/log";
|
||||
mountOptions = [
|
||||
"subvol=log"
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
swap = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "swap";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems."/persist".neededForBoot = true;
|
||||
fileSystems."/var/log".neededForBoot = true;
|
||||
}
|
||||
35
machines/genepi/dns.nix
Normal file
35
machines/genepi/dns.nix
Normal file
@@ -0,0 +1,35 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
domain = "home.rpqt.fr";
|
||||
genepi = {
|
||||
ip = "100.83.123.79";
|
||||
subdomains = [
|
||||
"glance"
|
||||
"grafana"
|
||||
"images"
|
||||
"rss"
|
||||
"tw"
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
networking.firewall.interfaces."${config.services.tailscale.interfaceName}" = {
|
||||
allowedTCPPorts = [ 53 ];
|
||||
allowedUDPPorts = [ 53 ];
|
||||
};
|
||||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
resolveLocalQueries = false;
|
||||
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "${config.services.tailscale.interfaceName}" ];
|
||||
access-control = [ "100.0.0.0/8 allow" ];
|
||||
|
||||
local-zone = lib.map (subdomain: ''"${subdomain}.${domain}." redirect'') genepi.subdomains;
|
||||
local-data = lib.map (subdomain: ''"${subdomain}.${domain}. IN A ${genepi.ip}"'') genepi.subdomains;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
26
machines/genepi/freshrss.nix
Normal file
26
machines/genepi/freshrss.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
domain = "home.rpqt.fr";
|
||||
subdomain = "rss.${domain}";
|
||||
in
|
||||
{
|
||||
age.secrets.freshrss = {
|
||||
file = ../../secrets/freshrss.age;
|
||||
mode = "700";
|
||||
owner = config.services.freshrss.user;
|
||||
};
|
||||
|
||||
services.freshrss = {
|
||||
enable = true;
|
||||
baseUrl = "https://${subdomain}";
|
||||
virtualHost = "${subdomain}";
|
||||
|
||||
defaultUser = "rpqt";
|
||||
passwordFile = config.age.secrets.freshrss.path;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${config.services.freshrss.virtualHost} = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "${domain}";
|
||||
};
|
||||
}
|
||||
187
machines/genepi/glance-config.nix
Normal file
187
machines/genepi/glance-config.nix
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
theme = {
|
||||
light = true;
|
||||
background-color = "0 0 95";
|
||||
primary-color = "0 0 10";
|
||||
negative-color = "0 90 50";
|
||||
};
|
||||
pages = [
|
||||
{
|
||||
name = "Home";
|
||||
columns = [
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "calendar";
|
||||
first-day-of-week = "monday";
|
||||
}
|
||||
{
|
||||
type = "server-stats";
|
||||
servers = [
|
||||
{
|
||||
type = "local";
|
||||
name = "Genepi";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "full";
|
||||
widgets = [
|
||||
{
|
||||
type = "search";
|
||||
autofocus = true;
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "Services";
|
||||
sites = [
|
||||
{
|
||||
title = "Immich";
|
||||
url = "https://images.home.rpqt.fr";
|
||||
icon = "si:immich";
|
||||
}
|
||||
{
|
||||
title = "Grafana";
|
||||
url = "https://grafana.home.rpqt.fr";
|
||||
icon = "si:grafana";
|
||||
}
|
||||
{
|
||||
title = "FreshRSS";
|
||||
url = "https://rss.home.rpqt.fr";
|
||||
icon = "si:rss";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "weather";
|
||||
location = "Grenoble, France";
|
||||
units = "metric";
|
||||
hour-format = "24h";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
name = "Feeds";
|
||||
columns = [
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "rss";
|
||||
title = "Blogs";
|
||||
limit = 10;
|
||||
collapse-after = 5;
|
||||
cache = "12h";
|
||||
feeds = [
|
||||
{
|
||||
url = "https://rss.home.rpqt.fr/api/query.php?user=rpqt&t=74HfeLZ6Wu9h4MmjNR38Rz&f=rss";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "rss";
|
||||
title = "Status & Updates";
|
||||
limit = 3;
|
||||
cache = "12h";
|
||||
feeds = [
|
||||
{
|
||||
url = "https://status.sr.ht/index.xml";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "full";
|
||||
widgets = [
|
||||
{
|
||||
type = "group";
|
||||
widgets = [
|
||||
{
|
||||
type = "hacker-news";
|
||||
}
|
||||
{
|
||||
type = "lobsters";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "group";
|
||||
widgets = [
|
||||
{
|
||||
type = "reddit";
|
||||
subreddit = "selfhosted";
|
||||
show-thumbnails = true;
|
||||
}
|
||||
{
|
||||
type = "reddit";
|
||||
subreddit = "homelab";
|
||||
show-thumbnails = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "videos";
|
||||
channels = [
|
||||
"UCR-DXc1voovS8nhAvccRZhg"
|
||||
"UCsBjURrPoezykLs9EqgamOA"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "releases";
|
||||
cache = "1d";
|
||||
repositories = [
|
||||
"glanceapp/glance"
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "custom-api";
|
||||
title = "Random Fact";
|
||||
cache = "6h";
|
||||
url = "https://uselessfacts.jsph.pl/api/v2/facts/random";
|
||||
template = ''
|
||||
<p class="size-h4 color-paragraph">{{ .JSON.String "text" }}</p>
|
||||
'';
|
||||
}
|
||||
{
|
||||
type = "custom-api";
|
||||
title = "Steam Specials";
|
||||
cache = "12h";
|
||||
url = "https://store.steampowered.com/api/featuredcategories?cc=us";
|
||||
template = ''
|
||||
<ul class="list list-gap-10 collapsible-container" data-collapse-after="5">
|
||||
{{ range .JSON.Array "specials.items" }}
|
||||
<li>
|
||||
<a class="size-h4 color-highlight block text-truncate" href="https://store.steampowered.com/app/{{ .Int "id" }}/">{{ .String "name" }}</a>
|
||||
<ul class="list-horizontal-text">
|
||||
<li>{{ div (.Int "final_price" | toFloat) 100 | printf "$%.2f" }}</li>
|
||||
{{ $discount := .Int "discount_percent" }}
|
||||
<li{{ if ge $discount 40 }} class="color-positive"{{ end }}>{{ $discount }}% off</li>
|
||||
</ul>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
'';
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
18
machines/genepi/glance.nix
Normal file
18
machines/genepi/glance.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
domain = "home.rpqt.fr";
|
||||
subdomain = "glance.${domain}";
|
||||
in
|
||||
{
|
||||
services.glance = {
|
||||
enable = true;
|
||||
settings = ./glance-config.nix;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${subdomain} = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "${domain}";
|
||||
locations."/".proxyPass =
|
||||
"http://127.0.0.1:${toString config.services.glance.settings.server.port}";
|
||||
};
|
||||
}
|
||||
23
machines/genepi/hardware-configuration.nix
Normal file
23
machines/genepi/hardware-configuration.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{ inputs, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
# inputs.nixos-hardware.nixosModules.raspberry-pi-4
|
||||
];
|
||||
|
||||
nixpkgs.hostPlatform = "aarch64-linux";
|
||||
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
|
||||
# hardware = {
|
||||
# raspberry-pi."4".apply-overlays-dtmerge.enable = true;
|
||||
# deviceTree = {
|
||||
# enable = true;
|
||||
# filter = "*rpi-4-*.dtb";
|
||||
# };
|
||||
# };
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
libraspberrypi
|
||||
raspberrypi-eeprom
|
||||
];
|
||||
}
|
||||
32
machines/genepi/home.nix
Normal file
32
machines/genepi/home.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
home.username = "rpqt";
|
||||
home.homeDirectory = lib.mkForce "/home/rpqt";
|
||||
|
||||
home.packages = [
|
||||
pkgs.helix
|
||||
pkgs.ripgrep
|
||||
pkgs.eza
|
||||
];
|
||||
|
||||
programs.zsh.enable = true;
|
||||
programs.starship.enable = true;
|
||||
programs.atuin.enable = true;
|
||||
|
||||
# This value determines the Home Manager release that your configuration is
|
||||
# compatible with. This helps avoid breakage when a new Home Manager release
|
||||
# introduces backwards incompatible changes.
|
||||
#
|
||||
# You should not change this value, even if you update Home Manager. If you do
|
||||
# want to update the value, then make sure to first check the Home Manager
|
||||
# release notes.
|
||||
home.stateVersion = "24.11";
|
||||
|
||||
# Let Home Manager install and manage itself
|
||||
programs.home-manager.enable = true;
|
||||
}
|
||||
10
machines/genepi/homeassistant.nix
Normal file
10
machines/genepi/homeassistant.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
virtualisation.oci-containers.containers.homeassistant = {
|
||||
volumes = [ "home-assistant:/config" ];
|
||||
environment.TZ = "Europe/Paris";
|
||||
image = "ghcr.io/home-assistant/home-assistant:stable";
|
||||
extraOptions = [
|
||||
"--network=host"
|
||||
];
|
||||
};
|
||||
}
|
||||
30
machines/genepi/immich.nix
Normal file
30
machines/genepi/immich.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
domain = "home.rpqt.fr";
|
||||
subdomain = "images.${domain}";
|
||||
in
|
||||
{
|
||||
services.immich = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server.externalDomain = "https://${subdomain}";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${subdomain} = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "${domain}";
|
||||
locations."/" = {
|
||||
proxyPass = "http://${toString config.services.immich.host}:${toString config.services.immich.port}";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
client_max_body_size 50000M;
|
||||
proxy_read_timeout 600s;
|
||||
proxy_send_timeout 600s;
|
||||
send_timeout 600s;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
clan.core.state.userdata.folders = [ "/var/lib/immich" ];
|
||||
}
|
||||
6
machines/genepi/monitoring/default.nix
Normal file
6
machines/genepi/monitoring/default.nix
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
imports = [
|
||||
./grafana.nix
|
||||
./prometheus.nix
|
||||
];
|
||||
}
|
||||
40
machines/genepi/monitoring/grafana.nix
Normal file
40
machines/genepi/monitoring/grafana.nix
Normal file
@@ -0,0 +1,40 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
domain = "home.rpqt.fr";
|
||||
in
|
||||
{
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
http_port = 3000;
|
||||
domain = "grafana.${domain}";
|
||||
};
|
||||
};
|
||||
provision = {
|
||||
enable = true;
|
||||
datasources = {
|
||||
settings = {
|
||||
datasources = [
|
||||
{
|
||||
name = "Prometheus";
|
||||
type = "prometheus";
|
||||
access = "proxy";
|
||||
url = "http://127.0.0.1:${toString config.services.prometheus.port}";
|
||||
isDefault = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${config.services.grafana.settings.server.domain} = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "${domain}";
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString config.services.grafana.settings.server.http_port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
63
machines/genepi/monitoring/prometheus.nix
Normal file
63
machines/genepi/monitoring/prometheus.nix
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
let
|
||||
allHosts = self.nixosConfigurations;
|
||||
|
||||
hostInTailnetFilter = k: v: v.config.services.tailscale.enable;
|
||||
tailnetHosts = lib.filterAttrs hostInTailnetFilter allHosts;
|
||||
|
||||
# Explicitly list the exporters as some are deprecated and can't be evaluated
|
||||
possibleExporterNames = [
|
||||
"node"
|
||||
];
|
||||
|
||||
getEnabledExporters =
|
||||
hostname: host:
|
||||
lib.filterAttrs (k: v: v.enable == true) (
|
||||
lib.getAttrs possibleExporterNames host.config.services.prometheus.exporters
|
||||
);
|
||||
enabledExporters = lib.mapAttrs getEnabledExporters tailnetHosts;
|
||||
|
||||
mkScrapeConfigExporter = hostname: exporterName: exporterCfg: {
|
||||
job_name = "${hostname}-${exporterName}";
|
||||
static_configs = [ { targets = [ "${hostname}:${toString exporterCfg.port}" ]; } ];
|
||||
relabel_configs = [
|
||||
{
|
||||
target_label = "instance";
|
||||
replacement = "${hostname}";
|
||||
}
|
||||
{
|
||||
target_label = "job";
|
||||
replacement = "${exporterName}";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
mkScrapeConfigHost = hostname: exporters: lib.mapAttrs (mkScrapeConfigExporter hostname) exporters;
|
||||
scrapeConfigsByHost = lib.mapAttrs mkScrapeConfigHost enabledExporters;
|
||||
|
||||
autogenScrapeConfigs = lib.flatten (
|
||||
map builtins.attrValues (builtins.attrValues scrapeConfigsByHost)
|
||||
);
|
||||
in
|
||||
{
|
||||
services.prometheus = {
|
||||
enable = true;
|
||||
port = 9001;
|
||||
|
||||
scrapeConfigs = autogenScrapeConfigs;
|
||||
|
||||
exporters = {
|
||||
node = {
|
||||
enable = true;
|
||||
enabledCollectors = [ "systemd" ];
|
||||
port = 9002;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
clan.core.state.userdata.folders = [ "/var/lib/prometheus2" ];
|
||||
}
|
||||
27
machines/genepi/mpd.nix
Normal file
27
machines/genepi/mpd.nix
Normal file
@@ -0,0 +1,27 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
services.mpd = {
|
||||
enable = true;
|
||||
musicDirectory = "/home/rpqt/Media/Music";
|
||||
extraConfig = ''
|
||||
audio_output {
|
||||
type "pulse"
|
||||
name "Pulse Audio"
|
||||
}
|
||||
'';
|
||||
|
||||
network.listenAddress = "any";
|
||||
};
|
||||
|
||||
services.pulseaudio.enable = true;
|
||||
|
||||
# Workaround: run PulseAudio system-wide so that the mpd user can access it
|
||||
services.pulseaudio.systemWide = true;
|
||||
|
||||
# Fixes the stutter when changing volume (found this randomly)
|
||||
services.pulseaudio.daemon.config.flat-volumes = "no";
|
||||
|
||||
users.users.${config.services.mpd.user}.extraGroups = [ "pulse-access" ];
|
||||
|
||||
users.users.rpqt.homeMode = "755";
|
||||
}
|
||||
6
machines/genepi/network.nix
Normal file
6
machines/genepi/network.nix
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
# Tailscale seems to break when not using resolved
|
||||
services.resolved.enable = true;
|
||||
networking.useDHCP = true;
|
||||
networking.interfaces.tailscale0.useDHCP = false;
|
||||
}
|
||||
7
machines/genepi/nginx.nix
Normal file
7
machines/genepi/nginx.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
};
|
||||
}
|
||||
64
machines/genepi/persistence.nix
Normal file
64
machines/genepi/persistence.nix
Normal file
@@ -0,0 +1,64 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
environment.persistence."/persist" = {
|
||||
enable = true;
|
||||
directories = [
|
||||
"/var/lib/nixos"
|
||||
"/var/lib/acme"
|
||||
"/var/lib/prometheus2"
|
||||
"/var/lib/immich"
|
||||
"/var/lib/redis-immich"
|
||||
"/var/lib/postgresql"
|
||||
"/var/lib/grafana"
|
||||
"/var/lib/freshrss"
|
||||
"/var/lib/tailscale"
|
||||
];
|
||||
files = [
|
||||
# so that systemd doesn't think each boot is the first
|
||||
"/etc/machine-id"
|
||||
# ssh host keys
|
||||
"/etc/ssh/ssh_host_rsa_key"
|
||||
"/etc/ssh/ssh_host_rsa_key.pub"
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
];
|
||||
users.rpqt = {
|
||||
directories = [ ];
|
||||
files = [ ];
|
||||
home = "/home/rpqt";
|
||||
};
|
||||
};
|
||||
|
||||
# Empty root and remove snapshots older than 30 days
|
||||
# boot.initrd.postDeviceCommands = lib.mkAfter ''
|
||||
# mkdir /btrfs_tmp
|
||||
# mount /dev/disk/by-label/nixos /btrfs_tmp
|
||||
# if [[ -e /btrfs_tmp/root ]]; then
|
||||
# mkdir -p /btrfs_tmp/old_roots
|
||||
# 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 +30); do
|
||||
# delete_subvolume_recursively "$i"
|
||||
# done
|
||||
|
||||
# btrfs subvolume create /btrfs_tmp/root
|
||||
# umount /btrfs_tmp
|
||||
# rmdir /btrfs_tmp
|
||||
# '';
|
||||
|
||||
# Give agenix persistent paths so it can load secrets before the mount
|
||||
age.identityPaths = [
|
||||
"/persist/etc/ssh/ssh_host_ed25519_key"
|
||||
"/persist/etc/ssh/ssh_host_rsa_key"
|
||||
];
|
||||
}
|
||||
57
machines/genepi/syncthing.nix
Normal file
57
machines/genepi/syncthing.nix
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
user = "rpqt";
|
||||
home = config.users.users.${user}.home;
|
||||
in
|
||||
{
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
user = user;
|
||||
group = "users";
|
||||
dataDir = home;
|
||||
configDir = "${home}/.config/syncthing";
|
||||
openDefaultPorts = true;
|
||||
overrideDevices = true;
|
||||
overrideFolders = true;
|
||||
settings = {
|
||||
devices = {
|
||||
"haze" = {
|
||||
id = "QUX6KGF-7KNFTGD-RAX5OWC-NFQGRNK-S2TC2DQ-DQRWDTK-KMBTQXT-EVNRDQG";
|
||||
};
|
||||
"pixel-7a" = {
|
||||
id = "IZE7B4Z-LKTJY6Q-77NN4JG-ADYRC77-TYPZTXE-Q35BWV2-AEO7Q3R-ZE63IAU";
|
||||
};
|
||||
};
|
||||
folders = {
|
||||
"Documents" = {
|
||||
path = "${home}/Documents";
|
||||
devices = [
|
||||
"haze"
|
||||
];
|
||||
};
|
||||
"Music" = {
|
||||
path = "${home}/Media/Music";
|
||||
devices = [
|
||||
"haze"
|
||||
"pixel-7a"
|
||||
];
|
||||
};
|
||||
"Pictures" = {
|
||||
path = "${home}/Media/Pictures";
|
||||
devices = [
|
||||
"haze"
|
||||
];
|
||||
};
|
||||
"Videos" = {
|
||||
path = "${home}/Media/Videos";
|
||||
devices = [
|
||||
"haze"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
19
machines/genepi/taskchampion.nix
Normal file
19
machines/genepi/taskchampion.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
domain = "home.rpqt.fr";
|
||||
subdomain = "tw.${domain}";
|
||||
hasImpermanence = config.environment.persistence."/persist".enable;
|
||||
in
|
||||
{
|
||||
services.taskchampion-sync-server.enable = true;
|
||||
|
||||
services.taskchampion-sync-server.dataDir =
|
||||
(lib.optionalString hasImpermanence "/persist") + "/var/lib/taskchampion-sync-server";
|
||||
|
||||
services.nginx.virtualHosts.${subdomain} = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "${domain}";
|
||||
locations."/".proxyPass =
|
||||
"http://127.0.0.1:${toString config.services.taskchampion-sync-server.port}";
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user