mirror of
https://github.com/SebastianStork/nixos-config.git
synced 2026-01-21 15:11:34 +01:00
Remove host "stratus"
This commit is contained in:
parent
00ce882cb1
commit
8a4ca50606
21 changed files with 0 additions and 856 deletions
|
|
@ -3,7 +3,6 @@ keys:
|
||||||
- &alto age1qz04yg4h4g22wxqca2pd5k0z574223f6m5c9jy5ny37nlgcd6u4styf06t
|
- &alto age1qz04yg4h4g22wxqca2pd5k0z574223f6m5c9jy5ny37nlgcd6u4styf06t
|
||||||
- &fern age1sywwrwse76x8yskrsfpwk38fu2cmyx5s9qkf2pgc68cta0vj9psql7dp6e
|
- &fern age1sywwrwse76x8yskrsfpwk38fu2cmyx5s9qkf2pgc68cta0vj9psql7dp6e
|
||||||
- &north age18x6herevmcuhcmeh47ll6p9ck9zk4ga6gfxwlc8yl49rwjxm7qusylwfgc
|
- &north age18x6herevmcuhcmeh47ll6p9ck9zk4ga6gfxwlc8yl49rwjxm7qusylwfgc
|
||||||
- &stratus age1pryafed9elaea6zk5gnf6drjt4nznc02385y973lwt9t2s7j7vmsfnggkp
|
|
||||||
|
|
||||||
# Users
|
# Users
|
||||||
- &seb-admin age1mpq8m4p7dnxh5ze3fh7etd2k6sp85zdnmp9te3e9chcw4pw07pcq960zh5
|
- &seb-admin age1mpq8m4p7dnxh5ze3fh7etd2k6sp85zdnmp9te3e9chcw4pw07pcq960zh5
|
||||||
|
|
@ -27,11 +26,6 @@ creation_rules:
|
||||||
- age:
|
- age:
|
||||||
- *seb-admin
|
- *seb-admin
|
||||||
- *north
|
- *north
|
||||||
- path_regex: hosts/stratus/secrets.yaml$
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *seb-admin
|
|
||||||
- *stratus
|
|
||||||
|
|
||||||
# Users
|
# Users
|
||||||
- path_regex: users/seb/@fern/secrets.yaml$
|
- path_regex: users/seb/@fern/secrets.yaml$
|
||||||
|
|
|
||||||
|
|
@ -39,15 +39,9 @@ in
|
||||||
(mkHost "alto")
|
(mkHost "alto")
|
||||||
(mkHost "fern")
|
(mkHost "fern")
|
||||||
(mkHost "north")
|
(mkHost "north")
|
||||||
(mkHost "stratus")
|
|
||||||
];
|
];
|
||||||
|
|
||||||
deploy.nodes = {
|
deploy.nodes = {
|
||||||
stratus = {
|
|
||||||
hostname = "stratus";
|
|
||||||
sshUser = "root";
|
|
||||||
profiles.system.path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.stratus;
|
|
||||||
};
|
|
||||||
alto = {
|
alto = {
|
||||||
hostname = "alto";
|
hostname = "alto";
|
||||||
sshUser = "root";
|
sshUser = "root";
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
in
|
|
||||||
{
|
|
||||||
myConfig.resticBackup.${serviceName} = {
|
|
||||||
enable = true;
|
|
||||||
healthchecks.enable = true;
|
|
||||||
|
|
||||||
extraConfig = {
|
|
||||||
backupPrepareCommand = "${lib.getExe' pkgs.systemd "systemctl"} stop docker-actualbudget.service";
|
|
||||||
backupCleanupCommand = "${lib.getExe' pkgs.systemd "systemctl"} start docker-actualbudget.service docker-tailscale-actualbudget.service";
|
|
||||||
paths = [ "/data/${serviceName}" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [
|
|
||||||
(pkgs.writeShellApplication {
|
|
||||||
name = "${serviceName}-restore";
|
|
||||||
text = ''
|
|
||||||
systemctl stop docker-actualbudget.service
|
|
||||||
rm -rf /data/${serviceName}
|
|
||||||
restic-${serviceName} restore --target / latest
|
|
||||||
systemctl start docker-actualbudget.service docker-tailscale-actualbudget.service
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
subdomain = "budget";
|
|
||||||
|
|
||||||
serveConfig = builtins.toJSON {
|
|
||||||
TCP."443".HTTPS = true;
|
|
||||||
Web."${subdomain}.${config.networking.domain}:443".Handlers."/".Proxy = "http://127.0.0.1:5006";
|
|
||||||
};
|
|
||||||
configPath = pkgs.writeTextDir "tailscale-serve.json" serveConfig;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ ./backup.nix ];
|
|
||||||
|
|
||||||
virtualisation.oci-containers.containers = {
|
|
||||||
${serviceName} = {
|
|
||||||
image = "ghcr.io/actualbudget/actual-server@sha256:0cf0300ed4905045ed87e8892c26fbd83cd08e8499bb81dc28deef6afeb162fb";
|
|
||||||
volumes = [ "/data/${serviceName}:/data" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
"tailscale-${serviceName}" = {
|
|
||||||
environment.TS_HOSTNAME = subdomain;
|
|
||||||
volumes = [ "${configPath}:/config" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
containers = lib.filterAttrs (_: v: v == "directory") (builtins.readDir ./.);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = lib.mapAttrsToList (name: _: ./${name}) containers;
|
|
||||||
|
|
||||||
sops.secrets."container/tailscale-auth-key" = { };
|
|
||||||
|
|
||||||
virtualisation.oci-containers = {
|
|
||||||
backend = "docker";
|
|
||||||
|
|
||||||
containers = lib.mapAttrs' (
|
|
||||||
name: _:
|
|
||||||
lib.nameValuePair "tailscale-${name}" {
|
|
||||||
image = "ghcr.io/tailscale/tailscale@sha256:da35f0fbeb3037754049e3b079cb30c58c140576a50b54be107c0ff6ad0ec0e9";
|
|
||||||
environment = {
|
|
||||||
TS_STATE_DIR = "/var/lib/tailscale";
|
|
||||||
TS_SERVE_CONFIG = "/config/tailscale-serve.json";
|
|
||||||
TS_USERSPACE = "true"; # https://github.com/tailscale/tailscale/issues/11372
|
|
||||||
};
|
|
||||||
environmentFiles = [
|
|
||||||
# Contains "TS_AUTHKEY=<token>"
|
|
||||||
config.sops.secrets."container/tailscale-auth-key".path
|
|
||||||
];
|
|
||||||
volumes = [ "/var/lib/tailscale-${name}:/var/lib/tailscale" ];
|
|
||||||
extraOptions = [ "--network=container:${name}" ];
|
|
||||||
dependsOn = [ name ];
|
|
||||||
}
|
|
||||||
) containers;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
subdomain = "office";
|
|
||||||
|
|
||||||
serveConfig = builtins.toJSON {
|
|
||||||
TCP."443".HTTPS = true;
|
|
||||||
Web."${subdomain}.${config.networking.domain}:443".Handlers."/".Proxy = "http://127.0.0.1:80";
|
|
||||||
};
|
|
||||||
configPath = pkgs.writeTextDir "tailscale-serve.json" serveConfig;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sops.secrets."container/${serviceName}/jwt-secret" = { };
|
|
||||||
|
|
||||||
virtualisation.oci-containers.containers = {
|
|
||||||
${serviceName} = {
|
|
||||||
image = "onlyoffice/documentserver@sha256:3489a54c581414055dd9bfa3890435e5e6fc8c4ce0ffdd65cf3c7869f680cf81";
|
|
||||||
environmentFiles = [
|
|
||||||
# Contains "JWT_SECRET=<token>"
|
|
||||||
config.sops.secrets."container/${serviceName}/jwt-secret".path
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
"tailscale-${serviceName}" = {
|
|
||||||
environment.TS_HOSTNAME = subdomain;
|
|
||||||
volumes = [ "${configPath}:/config" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
subdomain = "pdf";
|
|
||||||
|
|
||||||
serveConfig = builtins.toJSON {
|
|
||||||
TCP."443".HTTPS = true;
|
|
||||||
Web."${subdomain}.${config.networking.domain}:443".Handlers."/".Proxy = "http://127.0.0.1:8080";
|
|
||||||
};
|
|
||||||
configPath = pkgs.writeTextDir "tailscale-serve.json" serveConfig;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
virtualisation.oci-containers.containers = {
|
|
||||||
${serviceName} = {
|
|
||||||
image = "frooodle/s-pdf@sha256:2a4a1483cd9f84e6af6281d84839ed15bb02d3818f02edad780f59e1c9e22a49";
|
|
||||||
environment = {
|
|
||||||
LANGS = "de_DE";
|
|
||||||
SYSTEM_SHOWUPDATE = "false";
|
|
||||||
};
|
|
||||||
volumes = [
|
|
||||||
"/data/stirling-pdf/tessdata:/usr/share/tessdata"
|
|
||||||
"/data/stirling-pdf/configs:/configs"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
"tailscale-${serviceName}" = {
|
|
||||||
environment.TS_HOSTNAME = subdomain;
|
|
||||||
volumes = [ "${configPath}:/config" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
self,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
containers = lib.filterAttrs (_: v: v == "directory") (builtins.readDir ./.);
|
|
||||||
dataDirOf = name: "/data/${name}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = lib.mapAttrsToList (name: _: ./${name}) containers;
|
|
||||||
|
|
||||||
sops.secrets = {
|
|
||||||
"container/tailscale-auth-key" = { };
|
|
||||||
"restic/environment" = { };
|
|
||||||
"restic/password" = { };
|
|
||||||
"healthchecks-ping-key" = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = lib.flatten (
|
|
||||||
lib.mapAttrsToList (name: _: [
|
|
||||||
"d ${dataDirOf name} - - -"
|
|
||||||
"d /var/lib/tailscale-${name} - - -"
|
|
||||||
]) containers
|
|
||||||
);
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
useDHCP = false;
|
|
||||||
bridges.br0.interfaces = [ "eno1" ];
|
|
||||||
interfaces."br0".useDHCP = true;
|
|
||||||
|
|
||||||
nat = {
|
|
||||||
enable = true;
|
|
||||||
internalInterfaces = [ "ve-+" ];
|
|
||||||
externalInterface = "br0";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
containers = lib.mapAttrs (name: _: {
|
|
||||||
autoStart = true;
|
|
||||||
ephemeral = true;
|
|
||||||
|
|
||||||
privateNetwork = true;
|
|
||||||
enableTun = true;
|
|
||||||
hostBridge = "br0";
|
|
||||||
|
|
||||||
bindMounts = {
|
|
||||||
# Secrets
|
|
||||||
"/run/secrets/tailscale-auth-key".hostPath = "/run/secrets/container/tailscale-auth-key";
|
|
||||||
"/run/secrets/container/${name}".isReadOnly = false;
|
|
||||||
"/run/secrets/restic".isReadOnly = false;
|
|
||||||
"/run/secrets/healthchecks-ping-key".isReadOnly = false;
|
|
||||||
|
|
||||||
# State
|
|
||||||
${dataDirOf name}.isReadOnly = false;
|
|
||||||
"/var/lib/tailscale" = {
|
|
||||||
hostPath = "/var/lib/tailscale-${name}";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
specialArgs = {
|
|
||||||
inherit inputs self;
|
|
||||||
inherit (config.system) stateVersion;
|
|
||||||
inherit (config.networking) domain;
|
|
||||||
dataDir = dataDirOf name;
|
|
||||||
};
|
|
||||||
config =
|
|
||||||
{
|
|
||||||
self,
|
|
||||||
stateVersion,
|
|
||||||
domain,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
imports = [ self.nixosModules.default ];
|
|
||||||
|
|
||||||
system = {
|
|
||||||
inherit stateVersion;
|
|
||||||
};
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
inherit domain;
|
|
||||||
useHostResolvConf = false;
|
|
||||||
interfaces."eth0".useDHCP = true;
|
|
||||||
nameservers = [
|
|
||||||
"8.8.8.8"
|
|
||||||
"1.1.1.1"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
services.resolved.enable = true;
|
|
||||||
|
|
||||||
myConfig.tailscale.enable = true;
|
|
||||||
};
|
|
||||||
}) containers;
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
dataDir,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
userName = config.services.forgejo.user;
|
|
||||||
groupName = config.services.forgejo.group;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
systemd.tmpfiles.rules = [ "d ${dataDir}/backup 750 ${userName} ${groupName} -" ];
|
|
||||||
|
|
||||||
security.polkit = {
|
|
||||||
enable = true;
|
|
||||||
extraConfig = ''
|
|
||||||
polkit.addRule(function(action, subject) {
|
|
||||||
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
|
||||||
action.lookup("unit") == "forgejo.service" &&
|
|
||||||
subject.user == "forgejo") {
|
|
||||||
return polkit.Result.YES;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
myConfig.resticBackup.${serviceName} = {
|
|
||||||
enable = true;
|
|
||||||
user = userName;
|
|
||||||
healthchecks.enable = true;
|
|
||||||
|
|
||||||
extraConfig = {
|
|
||||||
backupPrepareCommand = ''
|
|
||||||
${lib.getExe' pkgs.systemd "systemctl"} stop forgejo.service
|
|
||||||
${lib.getExe' config.services.postgresql.package "pg_dump"} forgejo --format=custom --file=${dataDir}/backup/db.dump
|
|
||||||
'';
|
|
||||||
backupCleanupCommand = ''
|
|
||||||
${lib.getExe' pkgs.systemd "systemctl"} start forgejo.service
|
|
||||||
'';
|
|
||||||
paths = [
|
|
||||||
"${dataDir}/home/custom"
|
|
||||||
"${dataDir}/home/data"
|
|
||||||
"${dataDir}/home/repositories"
|
|
||||||
"${dataDir}/home/.ssh"
|
|
||||||
"${dataDir}/backup"
|
|
||||||
];
|
|
||||||
extraBackupArgs = [ "--exclude='${dataDir}/home/custom/conf/app.ini'" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [
|
|
||||||
(pkgs.writeShellApplication {
|
|
||||||
name = "${serviceName}-restore";
|
|
||||||
text = ''
|
|
||||||
systemctl stop forgejo.service
|
|
||||||
sudo --user=${userName} restic-${serviceName} restore --target / latest
|
|
||||||
sudo --user=${userName} pg_restore --clean --if-exists --dbname forgejo ${dataDir}/backup/db.dump
|
|
||||||
systemctl start forgejo.service
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
subdomain = "git";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sops.secrets."container/forgejo/admin-password" = { };
|
|
||||||
|
|
||||||
containers.${serviceName}.config =
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
dataDir,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
userName = config.services.forgejo.user;
|
|
||||||
groupName = config.services.forgejo.group;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ ./backup.nix ];
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
|
||||||
"z /run/secrets/container/forgejo/admin-password - ${userName} ${groupName} -"
|
|
||||||
"d ${dataDir}/home 750 ${userName} ${groupName} -"
|
|
||||||
"d ${dataDir}/postgresql 700 postgres postgres -"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.postgresql.dataDir = "${dataDir}/postgresql";
|
|
||||||
|
|
||||||
services.forgejo = {
|
|
||||||
enable = true;
|
|
||||||
stateDir = "${dataDir}/home";
|
|
||||||
|
|
||||||
lfs.enable = true;
|
|
||||||
database.type = "postgres";
|
|
||||||
settings = {
|
|
||||||
server = {
|
|
||||||
DOMAIN = config.networking.fqdn;
|
|
||||||
ROOT_URL = "https://${config.services.forgejo.settings.server.DOMAIN}/";
|
|
||||||
};
|
|
||||||
service.DISABLE_REGISTRATION = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.forgejo.preStart = ''
|
|
||||||
create="${lib.getExe config.services.forgejo.package} admin user create"
|
|
||||||
$create --admin --email "sebastian.stork@pm.me" --username seb --password "$(cat /run/secrets/container/forgejo/admin-password)" || true
|
|
||||||
'';
|
|
||||||
|
|
||||||
myConfig.tailscale = {
|
|
||||||
inherit subdomain;
|
|
||||||
serve = "3000";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
subdomain = "rss";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sops.secrets."container/freshrss/admin-password" = { };
|
|
||||||
|
|
||||||
containers.${serviceName}.config =
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
domain,
|
|
||||||
dataDir,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
userName = config.users.users.freshrss.name;
|
|
||||||
groupName = config.users.groups.freshrss.name;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
systemd.tmpfiles.rules = [
|
|
||||||
"z /run/secrets/container/freshrss/admin-password - ${userName} ${groupName} -"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.freshrss = {
|
|
||||||
enable = true;
|
|
||||||
inherit dataDir;
|
|
||||||
baseUrl = "https://${subdomain}.${domain}";
|
|
||||||
defaultUser = "seb";
|
|
||||||
passwordFile = "/run/secrets/container/freshrss/admin-password";
|
|
||||||
};
|
|
||||||
|
|
||||||
myConfig.tailscale = {
|
|
||||||
inherit subdomain;
|
|
||||||
serve = "80";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
dataDir,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
userName = config.users.users.nextcloud.name;
|
|
||||||
groupName = config.users.users.nextcloud.group;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
systemd.tmpfiles.rules = [ "d ${dataDir}/backup 700 ${userName} ${groupName} -" ];
|
|
||||||
|
|
||||||
myConfig.resticBackup.${serviceName} = {
|
|
||||||
enable = true;
|
|
||||||
user = userName;
|
|
||||||
healthchecks.enable = true;
|
|
||||||
|
|
||||||
extraConfig = {
|
|
||||||
backupPrepareCommand = ''
|
|
||||||
${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --on
|
|
||||||
${lib.getExe' config.services.postgresql.package "pg_dump"} nextcloud --format=custom --file=${dataDir}/backup/db.dump
|
|
||||||
'';
|
|
||||||
backupCleanupCommand = ''
|
|
||||||
${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --off
|
|
||||||
'';
|
|
||||||
paths = [
|
|
||||||
"${dataDir}/home/data"
|
|
||||||
"${dataDir}/home/config/config.php"
|
|
||||||
"${dataDir}/backup"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [
|
|
||||||
(pkgs.writeShellApplication {
|
|
||||||
name = "${serviceName}-restore";
|
|
||||||
text = ''
|
|
||||||
sudo --user=${userName} ${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --on
|
|
||||||
sudo --user=${userName} restic-${serviceName} restore --target / latest
|
|
||||||
sudo --user=${userName} pg_restore --clean --if-exists --dbname nextcloud ${dataDir}/backup/db.dump
|
|
||||||
sudo --user=${userName} ${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --off
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
subdomain = "cloud";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sops.secrets = {
|
|
||||||
"container/nextcloud/admin-password" = { };
|
|
||||||
"container/nextcloud/gmail-password" = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
containers.${serviceName}.config =
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
pkgs,
|
|
||||||
dataDir,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
userName = config.users.users.nextcloud.name;
|
|
||||||
groupName = config.users.users.nextcloud.group;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./email-server.nix
|
|
||||||
./backup.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
|
||||||
"z /run/secrets/container/nextcloud/admin-password - ${userName} ${groupName} -"
|
|
||||||
"d ${dataDir}/home 750 ${userName} ${groupName} -"
|
|
||||||
"d ${dataDir}/postgresql 700 postgres postgres -"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.postgresql.dataDir = "${dataDir}/postgresql";
|
|
||||||
|
|
||||||
services.nextcloud = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.nextcloud30;
|
|
||||||
home = "${dataDir}/home";
|
|
||||||
hostName = config.networking.fqdn;
|
|
||||||
|
|
||||||
database.createLocally = true;
|
|
||||||
config = {
|
|
||||||
dbtype = "pgsql";
|
|
||||||
adminuser = "admin";
|
|
||||||
adminpassFile = "/run/secrets/container/nextcloud/admin-password";
|
|
||||||
};
|
|
||||||
|
|
||||||
https = true;
|
|
||||||
settings = {
|
|
||||||
overwriteProtocol = "https";
|
|
||||||
trusted_domains = [ "${subdomain}.${config.networking.domain}" ];
|
|
||||||
trusted_proxies = [ "127.0.0.1" ];
|
|
||||||
log_type = "file";
|
|
||||||
default_phone_region = "DE";
|
|
||||||
maintenance_window_start = "2"; # UTC
|
|
||||||
defaultapp = "side_menu";
|
|
||||||
};
|
|
||||||
|
|
||||||
configureRedis = true;
|
|
||||||
maxUploadSize = "16G";
|
|
||||||
phpOptions."opcache.interned_strings_buffer" = "16";
|
|
||||||
|
|
||||||
autoUpdateApps = {
|
|
||||||
enable = true;
|
|
||||||
startAt = "04:00:00";
|
|
||||||
};
|
|
||||||
extraApps = {
|
|
||||||
inherit (config.services.nextcloud.package.packages.apps)
|
|
||||||
calendar
|
|
||||||
contacts
|
|
||||||
deck
|
|
||||||
onlyoffice
|
|
||||||
;
|
|
||||||
|
|
||||||
twofactor_totp = pkgs.fetchNextcloudApp {
|
|
||||||
url = inputs.nextcloud-twofactor-totp.outPath;
|
|
||||||
sha256 = inputs.nextcloud-twofactor-totp.narHash;
|
|
||||||
license = "agpl3Plus";
|
|
||||||
unpack = true;
|
|
||||||
};
|
|
||||||
side_menu = pkgs.fetchNextcloudApp {
|
|
||||||
url = inputs.nextcloud-side-menu.outPath;
|
|
||||||
sha256 = inputs.nextcloud-side-menu.narHash;
|
|
||||||
license = "agpl3Plus";
|
|
||||||
unpack = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.ffmpeg ];
|
|
||||||
|
|
||||||
myConfig.tailscale = {
|
|
||||||
inherit subdomain;
|
|
||||||
serve = "80";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
services.nextcloud.settings = {
|
|
||||||
mail_smtpmode = "sendmail";
|
|
||||||
mail_sendmailmode = "pipe";
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.msmtp = {
|
|
||||||
enable = true;
|
|
||||||
accounts.default = {
|
|
||||||
auth = true;
|
|
||||||
tls = true;
|
|
||||||
host = "smtp.gmail.com";
|
|
||||||
port = "587";
|
|
||||||
user = "nextcloud.stork";
|
|
||||||
from = "nextcloud.stork@gmail.com";
|
|
||||||
passwordeval = "cat /run/secrets/container/nextcloud/gmail-password";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
dataDir,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
userName = config.services.paperless.user;
|
|
||||||
groupName = config.users.users.${userName}.group;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
systemd.tmpfiles.rules = [ "d ${dataDir}/backup 700 ${userName} ${groupName} -" ];
|
|
||||||
|
|
||||||
users.users.paperless.extraGroups = [ "redis-paperless" ];
|
|
||||||
|
|
||||||
myConfig.resticBackup.${serviceName} = {
|
|
||||||
enable = true;
|
|
||||||
user = userName;
|
|
||||||
healthchecks.enable = true;
|
|
||||||
|
|
||||||
extraConfig = {
|
|
||||||
backupPrepareCommand = ''
|
|
||||||
${dataDir}/paperless-manage document_exporter ${dataDir}/backup ${
|
|
||||||
lib.concatStringsSep " " [
|
|
||||||
"--compare-checksums"
|
|
||||||
"--delete"
|
|
||||||
"--split-manifest"
|
|
||||||
"--use-filename-format"
|
|
||||||
"--no-progress-bar"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
paths = [ "${dataDir}/backup" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [
|
|
||||||
(pkgs.writeShellApplication {
|
|
||||||
name = "${serviceName}-restore";
|
|
||||||
text = ''
|
|
||||||
sudo --user=${userName} restic-${serviceName} restore --target / latest
|
|
||||||
sudo --user=${userName} ${dataDir}/paperless-manage document_importer ${dataDir}/backup
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
let
|
|
||||||
serviceName = lib.last (lib.splitString "/" (builtins.toString ./.)); # Parent directory name
|
|
||||||
subdomain = "paper";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sops.secrets."container/paperless/admin-password" = { };
|
|
||||||
|
|
||||||
containers.${serviceName}.config =
|
|
||||||
{ dataDir, ... }:
|
|
||||||
{
|
|
||||||
imports = [ ./backup.nix ];
|
|
||||||
|
|
||||||
services.paperless = {
|
|
||||||
enable = true;
|
|
||||||
inherit dataDir;
|
|
||||||
passwordFile = "/run/secrets/container/paperless/admin-password";
|
|
||||||
settings.PAPERLESS_OCR_LANGUAGE = "deu+eng";
|
|
||||||
};
|
|
||||||
|
|
||||||
myConfig.tailscale = {
|
|
||||||
inherit subdomain;
|
|
||||||
serve = "28981";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./containers/docker
|
|
||||||
./containers/nspawn
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "24.05";
|
|
||||||
|
|
||||||
myConfig = {
|
|
||||||
sops.enable = true;
|
|
||||||
boot.loader.systemdBoot.enable = true;
|
|
||||||
tailscale = {
|
|
||||||
enable = true;
|
|
||||||
ssh.enable = true;
|
|
||||||
exitNode.enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
{
|
|
||||||
disko.devices = {
|
|
||||||
disk =
|
|
||||||
let
|
|
||||||
luks-settings = {
|
|
||||||
settings = {
|
|
||||||
allowDiscards = true;
|
|
||||||
keyFile = "/dev/disk/by-id/usb-SMI_USB_DISK-0:0";
|
|
||||||
keyFileSize = 4096;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
one = {
|
|
||||||
type = "disk";
|
|
||||||
device = "/dev/nvme0n1";
|
|
||||||
content = {
|
|
||||||
type = "gpt";
|
|
||||||
partitions = {
|
|
||||||
ESP = {
|
|
||||||
type = "EF00";
|
|
||||||
size = "512M";
|
|
||||||
content = {
|
|
||||||
type = "filesystem";
|
|
||||||
format = "vfat";
|
|
||||||
mountpoint = "/boot";
|
|
||||||
mountOptions = [ "defaults" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
luks = {
|
|
||||||
size = "100%";
|
|
||||||
content = {
|
|
||||||
name = "cryptroot";
|
|
||||||
type = "luks";
|
|
||||||
content = {
|
|
||||||
type = "lvm_pv";
|
|
||||||
vg = "root-pool";
|
|
||||||
};
|
|
||||||
} // luks-settings;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
two = {
|
|
||||||
type = "disk";
|
|
||||||
device = "/dev/sda";
|
|
||||||
content = {
|
|
||||||
type = "gpt";
|
|
||||||
partitions.luks = {
|
|
||||||
size = "100%";
|
|
||||||
content = {
|
|
||||||
name = "cryptdata";
|
|
||||||
type = "luks";
|
|
||||||
content = {
|
|
||||||
type = "lvm_pv";
|
|
||||||
vg = "data-pool";
|
|
||||||
};
|
|
||||||
} // luks-settings;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
lvm_vg = {
|
|
||||||
root-pool = {
|
|
||||||
type = "lvm_vg";
|
|
||||||
lvs.root = {
|
|
||||||
size = "100%FREE";
|
|
||||||
content = {
|
|
||||||
type = "filesystem";
|
|
||||||
format = "ext4";
|
|
||||||
mountpoint = "/";
|
|
||||||
mountOptions = [ "defaults" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
data-pool = {
|
|
||||||
type = "lvm_vg";
|
|
||||||
lvs.data = {
|
|
||||||
size = "100%FREE";
|
|
||||||
content = {
|
|
||||||
type = "filesystem";
|
|
||||||
format = "ext4";
|
|
||||||
mountpoint = "/data";
|
|
||||||
mountOptions = [ "defaults" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
{ inputs, ... }:
|
|
||||||
{
|
|
||||||
imports = [ inputs.disko.nixosModules.default ];
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = "x86_64-linux";
|
|
||||||
|
|
||||||
hardware = {
|
|
||||||
enableRedistributableFirmware = true;
|
|
||||||
cpu.intel.updateMicrocode = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
boot = {
|
|
||||||
kernelModules = [ "kvm-intel" ];
|
|
||||||
initrd.kernelModules = [ "usb_storage" ];
|
|
||||||
initrd.availableKernelModules = [
|
|
||||||
"xhci_pci"
|
|
||||||
"ahci"
|
|
||||||
"nvme"
|
|
||||||
"sd_mod"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
zramSwap.enable = true;
|
|
||||||
services = {
|
|
||||||
thermald.enable = true;
|
|
||||||
fstrim.enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
seb-password: ENC[AES256_GCM,data:InhoM7Z63JuEHY3j85aSlNy/DtOlfi38gDGYVJ9Srl5Nf/qgYJhOR4VQAZpoyWbtcNogdO05ddQ6OOzTc9PPHNePP00wz3KWRQ==,iv:rLCKJ9wUL+3sjIaqwV89pYJtt/ERuoR4AAgbt9H4oHg=,tag:toe3ey02D85APFKXlm3mEg==,type:str]
|
|
||||||
tailscale-auth-key: ENC[AES256_GCM,data:wiANABnJ9nzaagyQtccudaquKBnlhF0o87gPRKYFmTmujNQvDth0+tf/C5c0fT+eSxtM/KyJj7ZNwx9swFc=,iv:yq1LWbNE/OQdccX6bsspzbk0FJLtDRVOvLO2kSJvOxQ=,tag:TqNQiU7J16B1/QtfBuOawA==,type:str]
|
|
||||||
container:
|
|
||||||
tailscale-auth-key: ENC[AES256_GCM,data:bmLCx0yhdLQNtxch7OtOfhhW111nnSWEtg4K/1lURcZeUGtgDPjdyhAlcCba7p7QJf+RXZyTdgDKJ/TL8DQ=,iv:gj8/xBwe92MCWcTMYqm427tKom15bBid6tmJSvVopPQ=,tag:EWcGZT3UKUtFQiLkLkulNQ==,type:str]
|
|
||||||
onlyoffice:
|
|
||||||
jwt-secret: ENC[AES256_GCM,data:JTrtVdMJC0U2iw7wJ0ZE2eQGy5rM5BqPHRLE0zQH/iDLAADY0QZP5xc=,iv:4R/1YcVQjLTcEKJbQ5oq1/vUM+dc4zBLkFLSgH4wq0w=,tag:YIg2GV18hm2oYvTS6o6bUQ==,type:str]
|
|
||||||
forgejo:
|
|
||||||
admin-password: ENC[AES256_GCM,data:hBaD9s1EPm6pA+IH7i/ZsNrOTdiGCm5Lb2Hwd3BR,iv:2gmdO1dImo3fZWRaO3oyt3/IfD3zscHwxgv0iwgAMgQ=,tag:9ha9UP8u1ALQUWqpu8o1cw==,type:str]
|
|
||||||
freshrss:
|
|
||||||
admin-password: ENC[AES256_GCM,data:WlF90o4sHHXg2WzDiC/BbyYPpj6VCcmmNYDipl17,iv:8OdmIKQ3AHGUCE83pslrCWk+/IUVBmnjryfw8KrEBUk=,tag:mFEDPlO6uEN5uy70f9V+CQ==,type:str]
|
|
||||||
nextcloud:
|
|
||||||
admin-password: ENC[AES256_GCM,data:5b+Knl8ZFBL2H91FBqG6LGbx7+VqMryQjfQnUGCE,iv:4Nja7A+VyPPBiJP42fhDTWe93MmBo4/X8IMTR5PGo3s=,tag:ii22+1zaaE3MXj+A86Y/Yw==,type:str]
|
|
||||||
gmail-password: ENC[AES256_GCM,data:r/Do22VT42fxR4ZmcsuFia88YYA=,iv:5oVZRC/L9//pA/vqlk79WNoAdHO+c8CVhywYFRC15eA=,tag:2s/G6YDieF+z8ayHo02Jwg==,type:str]
|
|
||||||
paperless:
|
|
||||||
admin-password: ENC[AES256_GCM,data:7eO/qQ4/k9G93yykVyzt6JG0QeE=,iv:rfPMMiCCYxgQa5k+9RWRKpIkkLWamzBg1cIrsGun9G8=,tag:Xe2EOiipIH4gHdCMuw7n+w==,type:str]
|
|
||||||
restic:
|
|
||||||
environment: ENC[AES256_GCM,data:AxcIe2HmqZcjWETidgB63Xh+5pxPJS2BXXFOXAIaqjI+j4Qm/txorgXkY/n8tOJnJWFmVI6vj4Uz8+MFl1rHx0NnjNE3ijutV2gvTsUUtR18JDnW6ks0h7tcuVix4RH7OHU=,iv:+ohpmCKu/KIEn4gcBn3hNDTF7qybQAe3uDWiQ8GAIVw=,tag:OLqmrivfoB+oobTNbbgnVw==,type:str]
|
|
||||||
password: ENC[AES256_GCM,data:IuOdnYu5EqGY0wCFVx86ztNphHO5xTtPDr1UfjA4,iv:XPPs61l6KWGA06uhRZid6rAgNfbHtcJWYjrD5QJrnlI=,tag:y/NgGKwvAO9PtF0qQmTp1Q==,type:str]
|
|
||||||
healthchecks-ping-key: ENC[AES256_GCM,data:hU3X/JiGlToyNW+8Nyo7Jpq7Jiriew==,iv:c+/jK+4SiCby3yKdjXq69PEyfCOhua9quGCj7OK0Nhc=,tag:Od/x0VxsbZwyRbHvjwxHpg==,type:str]
|
|
||||||
sops:
|
|
||||||
kms: []
|
|
||||||
gcp_kms: []
|
|
||||||
azure_kv: []
|
|
||||||
hc_vault: []
|
|
||||||
age:
|
|
||||||
- recipient: age1mpq8m4p7dnxh5ze3fh7etd2k6sp85zdnmp9te3e9chcw4pw07pcq960zh5
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZYlNWcmJLSUs0ZG5lM1Bq
|
|
||||||
TnpZVWlhYXdPNVdYZFJDK3NjSTVYS3hQazN3CmRhUnd2WjlvRW12U2dXK2tXQmVW
|
|
||||||
elFOWHNvcXA3VFRGNXlEY2UvdDB2VFkKLS0tIGhsTmU3dTdZenlQbkcyUW85dVJq
|
|
||||||
SFVjcWRWUVJaNkVxZ1RpTUxkcTJYOGsK7BYF7OWVTNwJdbN1cThUlEiAzZwPQyzN
|
|
||||||
AhzAq3SY7g1MBPfbfMq3Seok09CX3TpgwARYdzmWNyytkEKAB31xtQ==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1pryafed9elaea6zk5gnf6drjt4nznc02385y973lwt9t2s7j7vmsfnggkp
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByQUtwNlc4RDZJQnVYdDBt
|
|
||||||
OFpkSFRybWpSbm5lSW5rMFBuaW9oc0tqZDBZCmxvaWJGc3BkbmdKampyVVQwMjVI
|
|
||||||
Q01UTGNESU1RRjNNdk5tY21zYWRSMUkKLS0tIHVBMUF3Y1B3cXJjRVdqZDNiZTlX
|
|
||||||
b3daaTFONzZ0cUtVY3RHUUhWOE1xRUEK0X59xCmXm8IinpaHonDpo7+3DqnMCX3k
|
|
||||||
zbvxChaurZ1pgZr51B662m9OLhkjrQVnIKK8ujZAJg7TyyQD/UrFUw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2025-03-26T23:52:03Z"
|
|
||||||
mac: ENC[AES256_GCM,data:ZdLKrA5NPZmr7Oagtu3fbLfJKL1PDHajrqtAvJ7yj9NsgVEnHd8VWo2+NQWhrxqT3D47jDyhCgcZigiYkKc7MDJFFJByXlBCg5hKnN6gBe1tvnYbj7grgFs5SUo9SxuKzeKH3clriyLW1UQQI0tYvHHUuZmG2eAqDX+SHGWRlMs=,iv:2BmmqJyXeJOLwwnIQ5M2NJIqr/ux0DoD85D3VVrBVUk=,tag:gSQV/H98kfjvHQnxmJEIAQ==,type:str]
|
|
||||||
pgp: []
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.9.4
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{ imports = [ ../user.nix ]; }
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue