mirror of
https://gitlab.com/upRootNutrition/dotfiles.git
synced 2025-12-14 02:20:53 -06:00
test: setting up nas structure
This commit is contained in:
parent
4225970826
commit
a92229390e
36 changed files with 275 additions and 1039 deletions
|
|
@ -2,7 +2,6 @@
|
||||||
let
|
let
|
||||||
inherit (moduleFunctions.instancesFunctions)
|
inherit (moduleFunctions.instancesFunctions)
|
||||||
sslPath
|
sslPath
|
||||||
sopsPath
|
|
||||||
secretPath
|
secretPath
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -12,13 +11,16 @@ in
|
||||||
{
|
{
|
||||||
label = label;
|
label = label;
|
||||||
name = name;
|
name = name;
|
||||||
|
interfaces = {
|
||||||
|
interface0 = {
|
||||||
paths = {
|
paths = {
|
||||||
|
mntPaths = {
|
||||||
path0 = sslPath;
|
path0 = sslPath;
|
||||||
};
|
};
|
||||||
secretPaths = {
|
secretPaths = {
|
||||||
path0 = secretPath;
|
path0 = "${secretPath}/${name}";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
sops = {
|
|
||||||
path0 = "${sopsPath}/${name}";
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,37 +2,49 @@
|
||||||
let
|
let
|
||||||
inherit (moduleFunctions.instancesFunctions)
|
inherit (moduleFunctions.instancesFunctions)
|
||||||
domain0
|
domain0
|
||||||
servicePath
|
mntPath
|
||||||
sslPath
|
sslPath
|
||||||
sopsPath
|
secretPath
|
||||||
;
|
;
|
||||||
audiobookshelfLabel = "Audiobookshelf";
|
label = "Audiobookshelf";
|
||||||
audiobookshelfName = "audiobookshelf";
|
name = "audiobookshelf";
|
||||||
audiobookshelfSubdomain = "books";
|
subdomain = "books";
|
||||||
audiobookshelfDomain = "${audiobookshelfSubdomain}.${domain0}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
label = audiobookshelfLabel;
|
label = label;
|
||||||
name = audiobookshelfName;
|
name = name;
|
||||||
short = "Books";
|
short = "Books";
|
||||||
sops = {
|
|
||||||
path0 = "${sopsPath}/${audiobookshelfName}";
|
|
||||||
};
|
|
||||||
domains = {
|
|
||||||
url0 = audiobookshelfDomain;
|
|
||||||
};
|
|
||||||
subdomain = audiobookshelfSubdomain;
|
|
||||||
tags = [
|
tags = [
|
||||||
|
name
|
||||||
|
"audiobooks"
|
||||||
|
"reading"
|
||||||
];
|
];
|
||||||
paths = {
|
|
||||||
path0 = "${servicePath}/${audiobookshelfLabel}";
|
|
||||||
};
|
|
||||||
ports = {
|
ports = {
|
||||||
port0 = 8000;
|
port0 = 8000;
|
||||||
};
|
};
|
||||||
|
interfaces = {
|
||||||
|
interface0 =
|
||||||
|
let
|
||||||
|
domain = "${subdomain}.${domain0}";
|
||||||
|
secret = "${secretPath}/${name}";
|
||||||
|
ssl = "${sslPath}/${domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
domain = domain;
|
||||||
|
subdomain = subdomain;
|
||||||
|
paths = {
|
||||||
|
mntPaths = {
|
||||||
|
path0 = "${mntPath}/${name}";
|
||||||
|
};
|
||||||
|
secretPaths = {
|
||||||
|
path0 = secret;
|
||||||
|
};
|
||||||
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
cert = "${sslPath}/${audiobookshelfSubdomain}.${domain0}/fullchain.pem";
|
path = ssl;
|
||||||
key = "${sslPath}/${audiobookshelfSubdomain}.${domain0}/key.pem";
|
cert = "${ssl}/fullchain.pem";
|
||||||
|
key = "${ssl}/key.pem";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ moduleFunctions }:
|
{ moduleFunctions }:
|
||||||
let
|
let
|
||||||
inherit (moduleFunctions.instancesFunctions)
|
inherit (moduleFunctions.instancesFunctions)
|
||||||
sopsPath
|
dummy
|
||||||
;
|
;
|
||||||
|
|
||||||
caddyLabel = "Caddy";
|
caddyLabel = "Caddy";
|
||||||
|
|
@ -10,9 +10,7 @@ in
|
||||||
{
|
{
|
||||||
label = caddyLabel;
|
label = caddyLabel;
|
||||||
name = caddyName;
|
name = caddyName;
|
||||||
sops = {
|
short = dummy;
|
||||||
path0 = "${sopsPath}/${caddyName}";
|
|
||||||
};
|
|
||||||
ports = {
|
ports = {
|
||||||
port0 = 80;
|
port0 = 80;
|
||||||
port1 = 443;
|
port1 = 443;
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ let
|
||||||
;
|
;
|
||||||
label = "ComfyUI";
|
label = "ComfyUI";
|
||||||
name = "comfyui";
|
name = "comfyui";
|
||||||
domain = "${name}.${domain0}";
|
|
||||||
ssl = "${sslPath}/${domain}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
label = label;
|
label = label;
|
||||||
|
|
@ -20,12 +18,18 @@ in
|
||||||
"comfy"
|
"comfy"
|
||||||
"ui"
|
"ui"
|
||||||
];
|
];
|
||||||
domains = {
|
|
||||||
url0 = domain;
|
|
||||||
};
|
|
||||||
ports = {
|
ports = {
|
||||||
port0 = 8188;
|
port0 = 8188;
|
||||||
};
|
};
|
||||||
|
interfaces = {
|
||||||
|
interface0 =
|
||||||
|
let
|
||||||
|
domain = "${name}.${domain0}";
|
||||||
|
ssl = "${sslPath}/${domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
domain = domain;
|
||||||
|
paths = {
|
||||||
varPaths = {
|
varPaths = {
|
||||||
path0 = "${varPath}/${name}";
|
path0 = "${varPath}/${name}";
|
||||||
};
|
};
|
||||||
|
|
@ -35,9 +39,12 @@ in
|
||||||
secretPaths = {
|
secretPaths = {
|
||||||
path0 = "/run/secrets";
|
path0 = "/run/secrets";
|
||||||
};
|
};
|
||||||
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
path = ssl;
|
path = ssl;
|
||||||
cert = "${ssl}/fullchain.pem";
|
cert = "${ssl}/fullchain.pem";
|
||||||
key = "${ssl}/key.pem";
|
key = "${ssl}/key.pem";
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,12 @@ in
|
||||||
{
|
{
|
||||||
microvm = {
|
microvm = {
|
||||||
id = "vm-${name}";
|
id = "vm-${name}";
|
||||||
mac = "02:00:00:00:54:04";
|
mac = "02:00:00:00:60:70";
|
||||||
idUser = "vmuser-firefly";
|
idUser = "vmuser-firefly";
|
||||||
macUser = "02:00:00:00:00:04";
|
macUser = "02:00:00:00:00:70";
|
||||||
ip = "192.168.50.114";
|
ip = "192.168.50.70";
|
||||||
gate = "192.168.50.1";
|
gate = "192.168.50.1";
|
||||||
ssh = 2204;
|
ssh = 2570;
|
||||||
};
|
};
|
||||||
email = "noreply@${domain0}";
|
email = "noreply@${domain0}";
|
||||||
domain = domain;
|
domain = domain;
|
||||||
|
|
|
||||||
|
|
@ -4,42 +4,50 @@ let
|
||||||
domain0
|
domain0
|
||||||
servicePath
|
servicePath
|
||||||
sslPath
|
sslPath
|
||||||
sopsPath
|
secretPath
|
||||||
;
|
;
|
||||||
|
|
||||||
label = "Glance";
|
label = "Glance";
|
||||||
name = "glance";
|
name = "glance";
|
||||||
subdomain = "dashboard";
|
|
||||||
domain = "${subdomain}.${domain0}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
label = label;
|
label = label;
|
||||||
name = name;
|
name = name;
|
||||||
short = label;
|
short = label;
|
||||||
email = {
|
|
||||||
address0 = "noreply@${domain0}";
|
|
||||||
};
|
|
||||||
sops = {
|
|
||||||
path0 = "${sopsPath}/${name}";
|
|
||||||
};
|
|
||||||
domains = {
|
|
||||||
url0 = domain;
|
|
||||||
};
|
|
||||||
subdomain = subdomain;
|
|
||||||
tags = [
|
tags = [
|
||||||
"glance"
|
"glance"
|
||||||
"dashboard"
|
"dashboard"
|
||||||
"weather"
|
"weather"
|
||||||
"podcasts"
|
"podcasts"
|
||||||
];
|
];
|
||||||
paths = {
|
|
||||||
path0 = "${servicePath}/${label}";
|
|
||||||
};
|
|
||||||
ports = {
|
ports = {
|
||||||
port0 = 3434;
|
port0 = 3434;
|
||||||
};
|
};
|
||||||
|
interfaces = {
|
||||||
|
interface0 =
|
||||||
|
let
|
||||||
|
subdomain = "dashboard";
|
||||||
|
domain = "${subdomain}.${domain0}";
|
||||||
|
secret = "${secretPath}/${name}";
|
||||||
|
ssl = "${sslPath}/${domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
domain = domain;
|
||||||
|
subdomain = subdomain;
|
||||||
|
email = "noreply@${domain0}";
|
||||||
|
paths = {
|
||||||
|
mntPaths = {
|
||||||
|
path0 = "${servicePath}/${label}";
|
||||||
|
};
|
||||||
|
secretPath = {
|
||||||
|
path0 = secret;
|
||||||
|
};
|
||||||
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
cert = "${sslPath}/${subdomain}.${domain0}/fullchain.pem";
|
path = ssl;
|
||||||
key = "${sslPath}/${subdomain}.${domain0}/key.pem";
|
cert = "${ssl}/fullchain.pem";
|
||||||
|
key = "${ssl}/key.pem";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
{ moduleFunctions }:
|
|
||||||
let
|
|
||||||
inherit (moduleFunctions.instancesFunctions)
|
|
||||||
servicePath
|
|
||||||
sopsPath
|
|
||||||
;
|
|
||||||
|
|
||||||
label = "Matrix";
|
|
||||||
name = "matrix";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
label = label;
|
|
||||||
name = name;
|
|
||||||
short = label;
|
|
||||||
sops = {
|
|
||||||
path0 = "${sopsPath}/${name}";
|
|
||||||
};
|
|
||||||
subdomain = name;
|
|
||||||
tags = [
|
|
||||||
|
|
||||||
];
|
|
||||||
paths = {
|
|
||||||
path0 = "${servicePath}/${label}";
|
|
||||||
path1 = "";
|
|
||||||
path2 = "";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -35,12 +35,12 @@ in
|
||||||
subdomain = short;
|
subdomain = short;
|
||||||
microvm = {
|
microvm = {
|
||||||
id = "vm-${short}";
|
id = "vm-${short}";
|
||||||
mac = "02:00:00:00:56:09";
|
mac = "02:00:00:00:66:76";
|
||||||
idUser = "vmuser-${short}";
|
idUser = "vmuser-${short}";
|
||||||
macUser = "02:00:00:00:00:09";
|
macUser = "02:00:00:00:00:76";
|
||||||
ip = "192.168.50.119";
|
ip = "192.168.50.76";
|
||||||
gate = "192.168.50.1";
|
gate = "192.168.50.1";
|
||||||
ssh = 2209;
|
ssh = 2576;
|
||||||
};
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
path = ssl;
|
path = ssl;
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
{ moduleFunctions }:
|
|
||||||
let
|
|
||||||
inherit (moduleFunctions.instancesFunctions)
|
|
||||||
domain1
|
|
||||||
servicePath
|
|
||||||
sslPath
|
|
||||||
sopsPath
|
|
||||||
;
|
|
||||||
|
|
||||||
label = "Owncast";
|
|
||||||
name = "owncast";
|
|
||||||
subdomain = "stream";
|
|
||||||
domain = "${subdomain}.${domain1}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
label = label;
|
|
||||||
name = name;
|
|
||||||
short = "Cast";
|
|
||||||
sops = {
|
|
||||||
path0 = "${sopsPath}/${name}";
|
|
||||||
};
|
|
||||||
domains = {
|
|
||||||
url0 = domain;
|
|
||||||
};
|
|
||||||
subdomain = subdomain;
|
|
||||||
tags = [
|
|
||||||
|
|
||||||
];
|
|
||||||
paths = {
|
|
||||||
path0 = "${servicePath}/${label}";
|
|
||||||
path1 = "/mnt/media/storage/${name}";
|
|
||||||
};
|
|
||||||
ports = {
|
|
||||||
port0 = 9454;
|
|
||||||
port1 = 1935;
|
|
||||||
};
|
|
||||||
ssl = {
|
|
||||||
cert = "${sslPath}/${subdomain}.${domain1}/fullchain.pem";
|
|
||||||
key = "${sslPath}/${subdomain}.${domain1}/key.pem";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -2,36 +2,24 @@
|
||||||
let
|
let
|
||||||
inherit (moduleFunctions.instancesFunctions)
|
inherit (moduleFunctions.instancesFunctions)
|
||||||
domain1
|
domain1
|
||||||
servicePath
|
mntPath
|
||||||
sslPath
|
sslPath
|
||||||
sopsPath
|
|
||||||
;
|
;
|
||||||
|
|
||||||
label = "PeerTube";
|
label = "PeerTube";
|
||||||
name = "peertube";
|
name = "peertube";
|
||||||
subdomain = "video";
|
|
||||||
domain = "${subdomain}.${domain1}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
label = label;
|
label = label;
|
||||||
name = name;
|
name = name;
|
||||||
short = "Peer";
|
short = "Peer";
|
||||||
email = {
|
email = "noreply@${domain1}";
|
||||||
address0 = "noreply@${domain1}";
|
|
||||||
};
|
|
||||||
sops = {
|
|
||||||
path0 = "${sopsPath}/${name}";
|
|
||||||
};
|
|
||||||
domains = {
|
|
||||||
url0 = domain;
|
|
||||||
};
|
|
||||||
subdomain = subdomain;
|
|
||||||
tags = [
|
tags = [
|
||||||
|
name
|
||||||
|
"video"
|
||||||
|
"peer"
|
||||||
|
"fediverse"
|
||||||
];
|
];
|
||||||
paths = {
|
|
||||||
path0 = "${servicePath}/${label}";
|
|
||||||
};
|
|
||||||
ports = {
|
ports = {
|
||||||
port0 = 9000; # HTTP
|
port0 = 9000; # HTTP
|
||||||
port1 = 1935;
|
port1 = 1935;
|
||||||
|
|
@ -39,8 +27,30 @@ in
|
||||||
port3 = 5432;
|
port3 = 5432;
|
||||||
port4 = 52800;
|
port4 = 52800;
|
||||||
};
|
};
|
||||||
|
interfaces = {
|
||||||
|
interface0 =
|
||||||
|
let
|
||||||
|
subdomain = "video";
|
||||||
|
domain = "${subdomain}.${domain1}";
|
||||||
|
secret = "${sslPath}/${name}";
|
||||||
|
ssl = "${sslPath}/${domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
domain = domain;
|
||||||
|
subdomain = subdomain;
|
||||||
|
paths = {
|
||||||
|
mntPaths = {
|
||||||
|
path0 = "${mntPath}/${name}";
|
||||||
|
};
|
||||||
|
secretPath = {
|
||||||
|
path0 = secret;
|
||||||
|
};
|
||||||
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
cert = "${sslPath}/${subdomain}.${domain1}/fullchain.pem";
|
path = ssl;
|
||||||
key = "${sslPath}/${subdomain}.${domain1}/key.pem";
|
cert = "${ssl}/fullchain.pem";
|
||||||
|
key = "${ssl}/key.pem";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,12 @@ in
|
||||||
subdomain = short;
|
subdomain = short;
|
||||||
microvm = {
|
microvm = {
|
||||||
id = "vm-${short}";
|
id = "vm-${short}";
|
||||||
mac = "02:00:00:00:56:11";
|
mac = "02:00:00:00:69:79";
|
||||||
idUser = "vmuser-${short}";
|
idUser = "vmuser-${short}";
|
||||||
macUser = "02:00:00:00:00:11";
|
macUser = "02:00:00:00:00:79";
|
||||||
ip = "192.168.50.121";
|
ip = "192.168.50.79";
|
||||||
gate = "192.168.50.1";
|
gate = "192.168.50.1";
|
||||||
ssh = 2211;
|
ssh = 2579;
|
||||||
};
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
path = ssl;
|
path = ssl;
|
||||||
|
|
|
||||||
|
|
@ -2,43 +2,51 @@
|
||||||
let
|
let
|
||||||
inherit (moduleFunctions.instancesFunctions)
|
inherit (moduleFunctions.instancesFunctions)
|
||||||
domain0
|
domain0
|
||||||
servicePath
|
mntPath
|
||||||
|
secretPath
|
||||||
sslPath
|
sslPath
|
||||||
sopsPath
|
|
||||||
;
|
;
|
||||||
|
|
||||||
label = "SearXNG";
|
label = "SearXNG";
|
||||||
name = "searx";
|
name = "searx";
|
||||||
subdomain = "search";
|
|
||||||
domain = "${subdomain}.${domain0}";
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
label = label;
|
label = label;
|
||||||
name = name;
|
name = name;
|
||||||
short = "Sear";
|
short = "Sear";
|
||||||
email = {
|
|
||||||
address0 = "noreply@${domain0}";
|
|
||||||
};
|
|
||||||
sops = {
|
|
||||||
path0 = "${sopsPath}/${name}";
|
|
||||||
};
|
|
||||||
domains = {
|
|
||||||
url0 = domain;
|
|
||||||
};
|
|
||||||
subdomain = subdomain;
|
|
||||||
tags = [
|
tags = [
|
||||||
"search"
|
"search"
|
||||||
"sear"
|
"sear"
|
||||||
"searx"
|
"searx"
|
||||||
];
|
];
|
||||||
paths = {
|
|
||||||
path0 = "${servicePath}/${label}";
|
|
||||||
};
|
|
||||||
ports = {
|
ports = {
|
||||||
port0 = 8888;
|
port0 = 8888;
|
||||||
};
|
};
|
||||||
|
interfaces = {
|
||||||
|
interface0 =
|
||||||
|
let
|
||||||
|
subdomain = "search";
|
||||||
|
domain = "${subdomain}.${domain0}";
|
||||||
|
ssl = "${sslPath}/${domain}";
|
||||||
|
secret = "${secretPath}/${name}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
domain = domain;
|
||||||
|
email = "noreply@${domain0}";
|
||||||
|
subdomain = subdomain;
|
||||||
|
paths = {
|
||||||
|
mntPaths = {
|
||||||
|
path0 = "${mntPath}/${name}";
|
||||||
|
};
|
||||||
|
secretPaths = {
|
||||||
|
path0 = secret;
|
||||||
|
};
|
||||||
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
cert = "${sslPath}/${subdomain}.${domain0}/fullchain.pem";
|
path = ssl;
|
||||||
key = "${sslPath}/${subdomain}.${domain0}/key.pem";
|
cert = "${ssl}/fullchain.pem";
|
||||||
|
key = "${ssl}/key.pem";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ in
|
||||||
subdomain = name;
|
subdomain = name;
|
||||||
microvm = {
|
microvm = {
|
||||||
id = "vm-${id}";
|
id = "vm-${id}";
|
||||||
mac = "02:00:00:00:56:10";
|
mac = "02:00:00:00:75:85";
|
||||||
idUser = "vmuser-${id}";
|
idUser = "vmuser-${id}";
|
||||||
macUser = "02:00:00:00:00:10";
|
macUser = "02:00:00:00:00:85";
|
||||||
ip = "192.168.50.120";
|
ip = "192.168.50.85";
|
||||||
gate = "192.168.50.1";
|
gate = "192.168.50.1";
|
||||||
ssh = 2210;
|
ssh = 2585;
|
||||||
};
|
};
|
||||||
ssl = {
|
ssl = {
|
||||||
cert = "${ssl}/fullchain.pem";
|
cert = "${ssl}/fullchain.pem";
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,11 @@ in
|
||||||
nas
|
nas
|
||||||
sambaEris
|
sambaEris
|
||||||
;
|
;
|
||||||
|
inherit (modules.guests.firefly-iii) fireflyNick;
|
||||||
|
inherit (modules.guests.opencloud) opencloudNick;
|
||||||
|
inherit (modules.guests.photoprism) photoprismNick;
|
||||||
|
inherit (modules.guests.vaultwarden) vaultwardenNick;
|
||||||
|
inherit (modules.guests.syncthing) syncthingNick;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ let
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.people.users.${user0}) email;
|
inherit (flake.config.people.users.${user0}) email;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
service = instances.acme;
|
serviceCfg = instances.acme;
|
||||||
dns0 = instances.web.dns.provider0;
|
dns0 = instances.web.dns.provider0;
|
||||||
dns1 = instances.web.dns.provider1;
|
dns1 = instances.web.dns.provider1;
|
||||||
in
|
in
|
||||||
|
|
@ -29,7 +29,7 @@ in
|
||||||
"pass"
|
"pass"
|
||||||
];
|
];
|
||||||
sopsPath = secret: dns: {
|
sopsPath = secret: dns: {
|
||||||
path = "/var/lib/secrets/${instances.acme.name}/${dns}-${secret}";
|
path = "/var/lib/secrets/${serviceCfg.name}/${dns}-${secret}";
|
||||||
owner = "root";
|
owner = "root";
|
||||||
mode = "600";
|
mode = "600";
|
||||||
};
|
};
|
||||||
|
|
@ -50,7 +50,7 @@ in
|
||||||
|
|
||||||
systemd = {
|
systemd = {
|
||||||
tmpfiles.rules = [
|
tmpfiles.rules = [
|
||||||
"Z ${service.sops.path0} 755 ${service.name} ${service.name} -"
|
"Z ${serviceCfg.secretPaths.path0} 755 ${serviceCfg.name} ${serviceCfg.name} -"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ flake, ... }:
|
{ flake, ... }:
|
||||||
let
|
let
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
service = instances.caddy;
|
serviceCfg = instances.caddy;
|
||||||
|
|
||||||
importList =
|
importList =
|
||||||
let
|
let
|
||||||
|
|
@ -26,8 +26,8 @@ in
|
||||||
networking = {
|
networking = {
|
||||||
firewall = {
|
firewall = {
|
||||||
allowedTCPPorts = [
|
allowedTCPPorts = [
|
||||||
service.ports.port0 # 80
|
serviceCfg.ports.port0 # 80
|
||||||
service.ports.port1 # 443
|
serviceCfg.ports.port1 # 443
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,15 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) guestPath;
|
||||||
inherit (import ./config { inherit config flake pkgs; }) fireflyVM;
|
inherit (import ./config { inherit config flake pkgs; }) fireflyVM;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.people.users.${user0}) email;
|
inherit (flake.config.people.users.${user0}) email;
|
||||||
inherit (flake.config.services.instances) firefly-iii;
|
inherit (flake.config.services.instances) firefly-iii;
|
||||||
interface0Cfg = firefly-iii.interfaces.interface0;
|
interface0Cfg = firefly-iii.interfaces.interface0;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
fireflyNick = fireflyVM {
|
fireflyNick = fireflyVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
|
|
@ -19,7 +22,7 @@ let
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh0;
|
ssh = interface0Cfg.microvm.ssh0;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
mnt = "";
|
mnt = guestPath user0;
|
||||||
owner = email.address2;
|
owner = email.address2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -44,7 +47,4 @@ let
|
||||||
# host = "";
|
# host = "";
|
||||||
# owner = "";
|
# owner = "";
|
||||||
# };
|
# };
|
||||||
|
}
|
||||||
in
|
|
||||||
fireflyNick
|
|
||||||
# // fireflyStacie // fireflyGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,21 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) mntPath;
|
||||||
inherit (import ./config { inherit flake pkgs; }) forgejoVM;
|
inherit (import ./config { inherit flake pkgs; }) forgejoVM;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
|
|
||||||
interface0Cfg = instances.forgejo.interfaces.interface0;
|
interface0Cfg = instances.forgejo.interfaces.interface0;
|
||||||
|
in
|
||||||
|
{
|
||||||
forgejoNick = forgejoVM {
|
forgejoNick = forgejoVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = mntPath;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
};
|
};
|
||||||
in
|
}
|
||||||
forgejoNick
|
|
||||||
# // forgejoStacie // forgejoGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
labHelpers = {
|
labHelpers = {
|
||||||
|
mntPath = "/mnt/storage";
|
||||||
guestPath = user: "/mnt/storage/users/${user}/guests";
|
guestPath = user: "/mnt/storage/users/${user}/guests";
|
||||||
docsPath = user: "/mnt/storage/users/${user}/home/docs";
|
docsPath = user: "/mnt/storage/users/${user}/home/docs";
|
||||||
mediaPath = user: "/mnt/storage/users/${user}/home/media";
|
mediaPath = user: "/mnt/storage/users/${user}/home/media";
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,22 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) mntPath;
|
||||||
inherit (import ./config { inherit flake pkgs; }) jellyfinVM;
|
inherit (import ./config { inherit flake pkgs; }) jellyfinVM;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
|
|
||||||
interface0Cfg = instances.jellyfin.interfaces.interface0;
|
interface0Cfg = instances.jellyfin.interfaces.interface0;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
jellyfinNick = jellyfinVM {
|
jellyfinNick = jellyfinVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = mntPath;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
};
|
};
|
||||||
in
|
}
|
||||||
jellyfinNick
|
|
||||||
# // forgejoStacie // forgejoGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,22 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) mntPath;
|
||||||
inherit (import ./config { inherit flake pkgs; }) mastodonVM;
|
inherit (import ./config { inherit flake pkgs; }) mastodonVM;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
|
|
||||||
interface0Cfg = instances.mastodon.interfaces.interface0;
|
interface0Cfg = instances.mastodon.interfaces.interface0;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
mastodonNick = mastodonVM {
|
mastodonNick = mastodonVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = mntPath;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
};
|
};
|
||||||
in
|
}
|
||||||
mastodonNick
|
|
||||||
# // mastodonStacie // mastodonGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,13 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) mntPath;
|
||||||
inherit (import ./config { inherit flake pkgs; }) minecraftVM;
|
inherit (import ./config { inherit flake pkgs; }) minecraftVM;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
minecraftNick01 =
|
minecraftNick01 =
|
||||||
let
|
let
|
||||||
interfaceCfg = instances.minecraft.interfaces.interface0;
|
interfaceCfg = instances.minecraft.interfaces.interface0;
|
||||||
|
|
@ -20,7 +23,7 @@ let
|
||||||
userMac = interfaceCfg.microvm.macUser;
|
userMac = interfaceCfg.microvm.macUser;
|
||||||
ssh = interfaceCfg.microvm.ssh;
|
ssh = interfaceCfg.microvm.ssh;
|
||||||
port = interfaceCfg.microvm.port;
|
port = interfaceCfg.microvm.port;
|
||||||
mnt = "";
|
mnt = mntPath;
|
||||||
worldNumber = "01";
|
worldNumber = "01";
|
||||||
config = {
|
config = {
|
||||||
allow-flight = false;
|
allow-flight = false;
|
||||||
|
|
@ -67,7 +70,7 @@ let
|
||||||
userMac = interfaceCfg.microvm.macUser;
|
userMac = interfaceCfg.microvm.macUser;
|
||||||
ssh = interfaceCfg.microvm.ssh;
|
ssh = interfaceCfg.microvm.ssh;
|
||||||
port = interfaceCfg.microvm.port;
|
port = interfaceCfg.microvm.port;
|
||||||
mnt = "";
|
mnt = mntPath;
|
||||||
worldNumber = "02";
|
worldNumber = "02";
|
||||||
config = {
|
config = {
|
||||||
allow-flight = false;
|
allow-flight = false;
|
||||||
|
|
@ -101,5 +104,4 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
}
|
||||||
minecraftNick01 // minecraftNick02
|
|
||||||
|
|
|
||||||
|
|
@ -5,22 +5,36 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) mntPath guestPath;
|
||||||
inherit (import ./config { inherit flake pkgs; }) opencloudVM;
|
inherit (import ./config { inherit flake pkgs; }) opencloudVM;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.services.instances) opencloud;
|
inherit (flake.config.services.instances) opencloud;
|
||||||
|
|
||||||
interface0Cfg = opencloud.interfaces.interface0;
|
interface0Cfg = opencloud.interfaces.interface0;
|
||||||
|
interface1Cfg = opencloud.interfaces.interface1;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
opencloudNick = opencloudVM {
|
opencloudNick = opencloudVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = guestPath user0;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
opencloudProject = opencloudVM {
|
||||||
|
user = user0;
|
||||||
|
ip = interface1Cfg.microvm.ip;
|
||||||
|
mac = interface1Cfg.microvm.mac;
|
||||||
|
userMac = interface1Cfg.microvm.macUser;
|
||||||
|
ssh = interface1Cfg.microvm.ssh;
|
||||||
|
mnt = mntPath;
|
||||||
|
host = "${interface0Cfg.subdomain}.${flake.inputs.linkpage.secrets.domains.projectsite}";
|
||||||
|
};
|
||||||
|
|
||||||
# opencloudStacie = opencloudVM {
|
# opencloudStacie = opencloudVM {
|
||||||
# user = "stacie";
|
# user = "stacie";
|
||||||
# ip = ipAddress id1;
|
# ip = ipAddress id1;
|
||||||
|
|
@ -40,7 +54,4 @@ let
|
||||||
# mnt = guestPath "garnet";
|
# mnt = guestPath "garnet";
|
||||||
# host = "";
|
# host = "";
|
||||||
# };
|
# };
|
||||||
|
}
|
||||||
in
|
|
||||||
opencloudNick
|
|
||||||
# // opencloudStacie // opencloudGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ in
|
||||||
passwordFile = "/run/secrets/${user}-pass";
|
passwordFile = "/run/secrets/${user}-pass";
|
||||||
storagePath = "/var/lib/${serviceCfg.name}";
|
storagePath = "/var/lib/${serviceCfg.name}";
|
||||||
originalsPath = "/var/lib/${serviceCfg.name}-media";
|
originalsPath = "/var/lib/${serviceCfg.name}-media";
|
||||||
importPath = "photos";
|
|
||||||
address = "0.0.0.0";
|
address = "0.0.0.0";
|
||||||
};
|
};
|
||||||
openssh = {
|
openssh = {
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,22 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) guestPath mediaPath;
|
||||||
inherit (import ./config { inherit flake lib; }) photoprismVM;
|
inherit (import ./config { inherit flake lib; }) photoprismVM;
|
||||||
inherit (flake.config.services.instances) photoprism;
|
inherit (flake.config.services.instances) photoprism;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
interface0Cfg = photoprism.interfaces.interface0;
|
interface0Cfg = photoprism.interfaces.interface0;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
photoprismNick = photoprismVM {
|
photoprismNick = photoprismVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = guestPath user0;
|
||||||
data = "";
|
data = mediaPath user0;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,6 +44,4 @@ let
|
||||||
# data = mediaPath "stacie";
|
# data = mediaPath "stacie";
|
||||||
# };
|
# };
|
||||||
|
|
||||||
in
|
}
|
||||||
photoprismNick
|
|
||||||
# // photoprismStacie // photoprismGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,22 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) mntPath;
|
||||||
inherit (import ./config { inherit flake pkgs; }) qbittorrentVM;
|
inherit (import ./config { inherit flake pkgs; }) qbittorrentVM;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
|
|
||||||
interface0Cfg = instances.qbittorrent.interfaces.interface0;
|
interface0Cfg = instances.qbittorrent.interfaces.interface0;
|
||||||
|
|
||||||
qbittorrentNick = qbittorrentVM {
|
in
|
||||||
|
{
|
||||||
|
qbittorrentCeres = qbittorrentVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = mntPath;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
port = 51820;
|
port = 51820;
|
||||||
endpoint = "185.111.110.1";
|
endpoint = "185.111.110.1";
|
||||||
|
|
@ -25,6 +28,4 @@ let
|
||||||
dns = [ "10.2.0.1" ];
|
dns = [ "10.2.0.1" ];
|
||||||
key = "QPfiwJQmt5VLEOh1ufLbi1lj6LUnwQY0tgDSh3pWx1k=";
|
key = "QPfiwJQmt5VLEOh1ufLbi1lj6LUnwQY0tgDSh3pWx1k=";
|
||||||
};
|
};
|
||||||
in
|
}
|
||||||
qbittorrentNick
|
|
||||||
# // qbittorrentStacie // qbittorrentGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,12 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers)
|
||||||
|
docsPath
|
||||||
|
guestPath
|
||||||
|
mediaPath
|
||||||
|
miscPath
|
||||||
|
;
|
||||||
inherit (import ./config { inherit flake; }) syncthingVM;
|
inherit (import ./config { inherit flake; }) syncthingVM;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
|
|
@ -52,19 +58,19 @@ let
|
||||||
{
|
{
|
||||||
mountPoint = "/var/lib/${serviceCfg.name}/docs";
|
mountPoint = "/var/lib/${serviceCfg.name}/docs";
|
||||||
proto = "virtiofs";
|
proto = "virtiofs";
|
||||||
source = "";
|
source = docsPath user;
|
||||||
tag = "${serviceCfg.name}_${user}_docs";
|
tag = "${serviceCfg.name}_${user}_docs";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
mountPoint = "/var/lib/${serviceCfg.name}/media";
|
mountPoint = "/var/lib/${serviceCfg.name}/media";
|
||||||
proto = "virtiofs";
|
proto = "virtiofs";
|
||||||
source = "";
|
source = mediaPath user;
|
||||||
tag = "${serviceCfg.name}_${user}_media";
|
tag = "${serviceCfg.name}_${user}_media";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
mountPoint = "/var/lib/${serviceCfg.name}/misc";
|
mountPoint = "/var/lib/${serviceCfg.name}/misc";
|
||||||
proto = "virtiofs";
|
proto = "virtiofs";
|
||||||
source = "";
|
source = miscPath user;
|
||||||
tag = "${serviceCfg.name}_${user}_misc";
|
tag = "${serviceCfg.name}_${user}_misc";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -75,6 +81,8 @@ let
|
||||||
"d /var/lib/${serviceCfg.name}/misc 0755 ${serviceCfg.name} ${serviceCfg.name} -"
|
"d /var/lib/${serviceCfg.name}/misc 0755 ${serviceCfg.name} ${serviceCfg.name} -"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
syncthingNick =
|
syncthingNick =
|
||||||
let
|
let
|
||||||
phoneID = "OALKHLZ-OODUWVX-PAC2LI7-UMZMSZO-FELLRCD-RS4DHJS-PVA5YQK-WTFXXQI";
|
phoneID = "OALKHLZ-OODUWVX-PAC2LI7-UMZMSZO-FELLRCD-RS4DHJS-PVA5YQK-WTFXXQI";
|
||||||
|
|
@ -85,7 +93,7 @@ let
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = guestPath user0;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
folders = foldersHelper user0;
|
folders = foldersHelper user0;
|
||||||
devices = devicesHelper user0 phoneID "Phone" "192.168.50.8";
|
devices = devicesHelper user0 phoneID "Phone" "192.168.50.8";
|
||||||
|
|
@ -112,7 +120,4 @@ let
|
||||||
# syncID = "";
|
# syncID = "";
|
||||||
# deviceIP = "";
|
# deviceIP = "";
|
||||||
# };
|
# };
|
||||||
|
}
|
||||||
in
|
|
||||||
syncthingNick
|
|
||||||
# // syncthingStacie // syncthingGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,22 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (labHelpers) guestPath;
|
||||||
inherit (import ./config { inherit flake; }) vaultwardenVM;
|
inherit (import ./config { inherit flake; }) vaultwardenVM;
|
||||||
inherit (flake.config.people) user0;
|
inherit (flake.config.people) user0;
|
||||||
inherit (flake.config.services.instances) vaultwarden;
|
inherit (flake.config.services.instances) vaultwarden;
|
||||||
|
|
||||||
interface0Cfg = vaultwarden.interfaces.interface0;
|
interface0Cfg = vaultwarden.interfaces.interface0;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
vaultwardenNick = vaultwardenVM {
|
vaultwardenNick = vaultwardenVM {
|
||||||
user = user0;
|
user = user0;
|
||||||
ip = interface0Cfg.microvm.ip;
|
ip = interface0Cfg.microvm.ip;
|
||||||
mac = interface0Cfg.microvm.mac;
|
mac = interface0Cfg.microvm.mac;
|
||||||
userMac = interface0Cfg.microvm.macUser;
|
userMac = interface0Cfg.microvm.macUser;
|
||||||
ssh = interface0Cfg.microvm.ssh;
|
ssh = interface0Cfg.microvm.ssh;
|
||||||
mnt = "";
|
mnt = guestPath user0;
|
||||||
host = interface0Cfg.domain;
|
host = interface0Cfg.domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -40,6 +43,4 @@ let
|
||||||
# host = "";
|
# host = "";
|
||||||
# };
|
# };
|
||||||
|
|
||||||
in
|
}
|
||||||
vaultwardenNick
|
|
||||||
# // vaultwardenStacie // vaultwardenGarnet
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,9 @@ let
|
||||||
inherit (import ./config { inherit flake pkgs; }) websiteVM;
|
inherit (import ./config { inherit flake pkgs; }) websiteVM;
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
|
|
||||||
websiteNick =
|
in
|
||||||
|
{
|
||||||
|
websiteUpRoot =
|
||||||
let
|
let
|
||||||
websitePkg = flake.self.packages.${pkgs.system}.website;
|
websitePkg = flake.self.packages.${pkgs.system}.website;
|
||||||
interfaceCfg = instances.website.interfaces.interface0;
|
interfaceCfg = instances.website.interfaces.interface0;
|
||||||
|
|
@ -34,5 +36,4 @@ let
|
||||||
package = websitePkg;
|
package = websitePkg;
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
}
|
||||||
websiteNick // websiteProject
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ let
|
||||||
inherit (flake.config.services) instances;
|
inherit (flake.config.services) instances;
|
||||||
interfaceCfg = instances.zookeeper.interfaces.interface0;
|
interfaceCfg = instances.zookeeper.interfaces.interface0;
|
||||||
|
|
||||||
zookeeperNick =
|
in
|
||||||
|
{
|
||||||
|
zookeeperBot =
|
||||||
let
|
let
|
||||||
appPackage = flake.self.packages.${pkgs.system}.zookeeper;
|
appPackage = flake.self.packages.${pkgs.system}.zookeeper;
|
||||||
in
|
in
|
||||||
|
|
@ -21,5 +23,4 @@ let
|
||||||
package = appPackage;
|
package = appPackage;
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
}
|
||||||
zookeeperNick
|
|
||||||
|
|
|
||||||
|
|
@ -24,20 +24,18 @@ in
|
||||||
};
|
};
|
||||||
paths =
|
paths =
|
||||||
let
|
let
|
||||||
inst = instance: instances.${instance}.mntPaths.path0;
|
inst = instance: interface: instances.${instance}.interfaces.${interface}.paths.mntPaths.path0;
|
||||||
in
|
in
|
||||||
[
|
[
|
||||||
"/home/${user0}/.ssh"
|
"/home/${user0}/.ssh"
|
||||||
(inst "firefly-iii")
|
(inst "forgejo" "interface0")
|
||||||
(inst "forgejo")
|
(inst "mastodon" "interface0")
|
||||||
(inst "mastodon")
|
(inst "opencloud" "interface1")
|
||||||
(inst "opencloud1")
|
(inst "minecraft" "interface0")
|
||||||
(inst "minecraft0")
|
(inst "minecraft" "interface1")
|
||||||
(inst "minecraft1")
|
((inst "jellyfin" "interface0") + "/cache")
|
||||||
(inst "vaultwarden")
|
((inst "jellyfin" "interface0") + "/data")
|
||||||
((inst "jellyfin") + "/cache")
|
((inst "jellyfin" "interface0") + "/media/music")
|
||||||
((inst "jellyfin") + "/data")
|
|
||||||
((inst "jellyfin") + "/media/music")
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
flake,
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
serverHelpers = {
|
|
||||||
ipAddress = ip: "192.168.50.${ip}";
|
|
||||||
mntPath = "/mnt/storage";
|
|
||||||
minecraft = {
|
|
||||||
id0 = 40;
|
|
||||||
id1 = 41;
|
|
||||||
id2 = 42;
|
|
||||||
ssh0 = 2440;
|
|
||||||
ssh1 = 2441;
|
|
||||||
ssh2 = 2442;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
minecraft = import ./guests/firefly-iii { inherit serverHelpers; };
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
minecraft
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
let
|
|
||||||
importList =
|
|
||||||
let
|
|
||||||
content = builtins.readDir ./.;
|
|
||||||
dirContent = builtins.filter (n: content.${n} == "directory") (builtins.attrNames content);
|
|
||||||
in
|
|
||||||
map (name: ./. + "/${name}") dirContent;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = importList;
|
|
||||||
}
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
{
|
|
||||||
flake,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
inherit (flake.config.machines.devices) ceres;
|
|
||||||
inherit (flake.config.services) instances;
|
|
||||||
|
|
||||||
service = instances.postgresql;
|
|
||||||
# backupPath = "${instances.syncthing.paths.path1}/${service.name}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
services = {
|
|
||||||
postgresqlBackup = {
|
|
||||||
enable = true;
|
|
||||||
# location = backupPath;
|
|
||||||
# compression = "zstd";
|
|
||||||
startAt = "*-*-* 07:00:00";
|
|
||||||
databases = [
|
|
||||||
instances.mastodon.name
|
|
||||||
instances.firefly-iii.name
|
|
||||||
];
|
|
||||||
};
|
|
||||||
postgresql = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
networking = {
|
|
||||||
firewall = {
|
|
||||||
allowedTCPPorts = [
|
|
||||||
service.ports.port0
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/var/lib/postgresql" = {
|
|
||||||
device = service.paths.path0;
|
|
||||||
fsType = "none";
|
|
||||||
options = [
|
|
||||||
"bind"
|
|
||||||
];
|
|
||||||
depends = [
|
|
||||||
ceres.storage0.mount
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.${service.name}.extraGroups = [
|
|
||||||
instances.mastodon.name
|
|
||||||
instances.forgejo.name
|
|
||||||
instances.syncthing.name
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services.sync-postgres-backups = {
|
|
||||||
description = "Sync PostgreSQL backups to Syncthing";
|
|
||||||
after = [
|
|
||||||
"postgresqlBackup-firefly-iii.service"
|
|
||||||
"postgresqlBackup-mastodon.service"
|
|
||||||
];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
User = instances.syncthing.name;
|
|
||||||
Group = instances.syncthing.name;
|
|
||||||
};
|
|
||||||
script = ''
|
|
||||||
${pkgs.rsync}/bin/rsync -av --delete \
|
|
||||||
/var/backup/postgresql/ \
|
|
||||||
${instances.syncthing.paths.path1}/${service.name}/
|
|
||||||
|
|
||||||
${pkgs.rsync}/bin/rsync -av --delete \
|
|
||||||
/var/lib/${instances.firefly-iii.name}/storage/ \
|
|
||||||
${instances.syncthing.paths.path1}/${service.name}/firefly-iii-storage/
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.timers.sync-postgres-backups = {
|
|
||||||
wantedBy = [ "timers.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnCalendar = "*-*-* 22:10:00"; # 10 mins after backup
|
|
||||||
Persistent = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
flake,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
inherit (flake.config.services) instances;
|
|
||||||
|
|
||||||
service = instances.postgresql;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
services = {
|
|
||||||
postgresqlBackup = {
|
|
||||||
enable = true;
|
|
||||||
startAt = "*-*-* 07:00:00";
|
|
||||||
};
|
|
||||||
postgresql = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
firewall = {
|
|
||||||
allowedTCPPorts = [
|
|
||||||
service.ports.port0
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,616 +0,0 @@
|
||||||
# ============================================================================
|
|
||||||
# MicroVM Service Template - Production-Ready Configuration
|
|
||||||
# ============================================================================
|
|
||||||
# This template is based on proven, working configurations from:
|
|
||||||
# - Vaultwarden (simple service with environment file)
|
|
||||||
# - Forgejo (complex service with separate secret files)
|
|
||||||
# - Jellyfin (media service with multiple mounts and tmpfiles)
|
|
||||||
#
|
|
||||||
# CRITICAL SUCCESS FACTORS (learned from production deployments):
|
|
||||||
# 1. Use serviceCfg.name for all service references (not hardcoded strings)
|
|
||||||
# 2. Secrets MUST use service-specific subdirectories: /run/secrets/${serviceCfg.name}/
|
|
||||||
# 3. Host directories MUST exist with correct permissions BEFORE VM starts
|
|
||||||
# 4. Use 0777 permissions when VM service runs as non-root user with different UID
|
|
||||||
# 5. systemd.tmpfiles can be used INSIDE the VM for VM-internal directories
|
|
||||||
# 6. Host and VM tmpfiles rules serve different purposes - use both when needed
|
|
||||||
#
|
|
||||||
# Architecture Overview:
|
|
||||||
# ┌────────────────────────────────────────────────┐
|
|
||||||
# │ Host (NixOS Server) │
|
|
||||||
# │ │
|
|
||||||
# │ ┌──────────────┐ ┌──────────────┐ │
|
|
||||||
# │ │ Caddy │ │ br-vms │ │
|
|
||||||
# │ │ (Reverse │──────│ Bridge │ │
|
|
||||||
# │ │ Proxy) │ │ 192.168.50 │ │
|
|
||||||
# │ │ TLS Term │ │ .240 │ │
|
|
||||||
# │ └──────────────┘ └──────┬───────┘ │
|
|
||||||
# │ :443 │ │
|
|
||||||
# │ │ ┌─────▼──────┐ │
|
|
||||||
# │ │ │ vm-NAME │ │
|
|
||||||
# │ │ │ (TAP) │ │
|
|
||||||
# │ │ └─────┬──────┘ │
|
|
||||||
# │ │ │ │
|
|
||||||
# │ ┌─────▼──────────────────────▼────────────┐ │
|
|
||||||
# │ │ │ │
|
|
||||||
# │ │ MicroVM Guest │ │
|
|
||||||
# │ │ ┌────────────┐ ┌────────────┐ │ │
|
|
||||||
# │ │ │ Service │ │ enp0s5 │ │ │
|
|
||||||
# │ │ │ :PORT │ │192.168.50 │ │ │
|
|
||||||
# │ │ │ │ │ .1XX │ │ │
|
|
||||||
# │ │ └────────────┘ └────────────┘ │ │
|
|
||||||
# │ │ │ │
|
|
||||||
# │ │ VirtioFS Mounts: │ │
|
|
||||||
# │ │ • /nix/.ro-store → Host /nix/store │ │
|
|
||||||
# │ │ • /var/lib/NAME → Host /mnt/storage │ │
|
|
||||||
# │ │ • /run/secrets → Host /run/secrets/NAME│ │
|
|
||||||
# │ └─────────────────────────────────────────┘ │
|
|
||||||
# │ │
|
|
||||||
# └────────────────────────────────────────────────┘
|
|
||||||
#
|
|
||||||
# Network Flow:
|
|
||||||
# 1. Internet → Router:443 (port forward) → Host:443 (Caddy)
|
|
||||||
# 2. Caddy terminates TLS using ACME certificates
|
|
||||||
# 3. Caddy proxies HTTP to VM's LAN IP (e.g., 192.168.50.151:8085)
|
|
||||||
# 4. Request: br-vms → TAP (vm-NAME) → VM enp0s5 → Service
|
|
||||||
# 5. Response follows same path in reverse
|
|
||||||
#
|
|
||||||
# IMPORTANT: Split-DNS for LAN Access
|
|
||||||
# - External users: DNS resolves to public IP → router forwards to host
|
|
||||||
# - Internal users: MUST have DNS resolve to 192.168.50.240 (host bridge IP)
|
|
||||||
# OR use /etc/hosts entries, otherwise NAT hairpinning may fail
|
|
||||||
#
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
flake,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
# ============================================================================
|
|
||||||
# CONFIGURATION REFERENCES
|
|
||||||
# ============================================================================
|
|
||||||
# These pull from your centralized instance definitions
|
|
||||||
# Located in: modules/config/instances/config/*.nix
|
|
||||||
|
|
||||||
inherit (flake.config.people) user0;
|
|
||||||
inherit (flake.config.services) instances;
|
|
||||||
|
|
||||||
# REPLACE 'service' with your actual service name identifier
|
|
||||||
# This should match the attribute name in your instances configuration
|
|
||||||
# Examples: vaultwarden, forgejo, jellyfin, etc.
|
|
||||||
serviceCfg = instances.service; # CHANGE THIS
|
|
||||||
|
|
||||||
# SMTP configuration (if your service needs email)
|
|
||||||
# Remove this line if your service doesn't use SMTP
|
|
||||||
smtpCfg = instances.smtp;
|
|
||||||
|
|
||||||
# Host/web configuration for routing and DNS
|
|
||||||
hostCfg = instances.web;
|
|
||||||
|
|
||||||
# Service domain (e.g., "service.example.com")
|
|
||||||
host = serviceCfg.domains.url0;
|
|
||||||
|
|
||||||
# DNS provider for ACME DNS-01 challenge
|
|
||||||
dns0 = instances.web.dns.provider0;
|
|
||||||
dns0Path = "dns/${dns0}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# ============================================================================
|
|
||||||
# HOST-SIDE CONFIGURATION
|
|
||||||
# ============================================================================
|
|
||||||
# These configurations run on the HOST, not inside the VM
|
|
||||||
# They MUST be configured BEFORE the VM starts
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# 1. Caddy Group Membership
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# Allow Caddy to read ACME certificates
|
|
||||||
users.users.caddy.extraGroups = [ "acme" ];
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# 2. ACME TLS Certificate
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# Request Let's Encrypt certificate using DNS-01 challenge
|
|
||||||
security.acme.certs."${host}" = {
|
|
||||||
dnsProvider = dns0;
|
|
||||||
environmentFile = config.sops.secrets.${dns0Path}.path;
|
|
||||||
group = "caddy";
|
|
||||||
};
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# 3. Host Storage Directories
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# Create directories on the host BEFORE VM starts
|
|
||||||
# The VM will mount these via VirtioFS
|
|
||||||
#
|
|
||||||
# PERMISSION PATTERNS (choose based on your service):
|
|
||||||
# - 0755: Safe default when VM service runs as root
|
|
||||||
# - 0777: Required when VM service runs as non-root with different UID
|
|
||||||
# (e.g., jellyfin runs as UID 999 inside VM)
|
|
||||||
#
|
|
||||||
# EXAMPLES FROM WORKING CONFIGS:
|
|
||||||
# Vaultwarden: "d ${serviceCfg.mntPaths.path0} 0777 root root -"
|
|
||||||
# Forgejo: "d ${serviceCfg.mntPaths.path0} 0777 root root -"
|
|
||||||
# Jellyfin: "d ${serviceCfg.mntPaths.path0} 0777 root root -"
|
|
||||||
# "d ${serviceCfg.mntPaths.path0}/cache 0777 root root -"
|
|
||||||
systemd.tmpfiles.rules = [
|
|
||||||
# Main data directory
|
|
||||||
"d ${serviceCfg.mntPaths.path0} 0777 root root -"
|
|
||||||
|
|
||||||
# OPTIONAL: Additional directories if needed (like Jellyfin's cache)
|
|
||||||
# "d ${serviceCfg.mntPaths.path0}/cache 0777 root root -"
|
|
||||||
];
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# 4. Secrets Management (SOPS)
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
|
||||||
# Configure secrets decryption on the host
|
|
||||||
# SOPS-nix will decrypt these to /run/secrets/${serviceCfg.name}/*
|
|
||||||
#
|
|
||||||
# CRITICAL: Always use ${serviceCfg.name} for the path prefix!
|
|
||||||
# This prevents conflicts between multiple VMs
|
|
||||||
#
|
|
||||||
# PATTERN 1: Single environment file (like Vaultwarden)
|
|
||||||
# sops.secrets = {
|
|
||||||
# "${serviceCfg.name}/env" = {
|
|
||||||
# owner = "root";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# PATTERN 2: Multiple secret files (like Forgejo)
|
|
||||||
# sops.secrets = {
|
|
||||||
# "${serviceCfg.name}/smtp" = {
|
|
||||||
# owner = "root";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
# "${serviceCfg.name}/database" = {
|
|
||||||
# owner = "root";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# PATTERN 3: No secrets (like Jellyfin - if service doesn't need secrets)
|
|
||||||
# sops.secrets = {};
|
|
||||||
|
|
||||||
sops.secrets = {
|
|
||||||
# CHOOSE ONE OF THE PATTERNS ABOVE AND UNCOMMENT
|
|
||||||
# "${serviceCfg.name}/env" = {
|
|
||||||
# owner = "root";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
};
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# CADDY REVERSE PROXY (Host-Side)
|
|
||||||
# ============================================================================
|
|
||||||
# Caddy terminates TLS and proxies to the VM
|
|
||||||
services.caddy.virtualHosts."${host}" = {
|
|
||||||
extraConfig = ''
|
|
||||||
# Forward all requests to the VM's IP and port
|
|
||||||
reverse_proxy ${serviceCfg.interface.ip}:${toString serviceCfg.ports.port0} {
|
|
||||||
# Pass the real client IP to the service
|
|
||||||
header_up X-Real-IP {remote_host}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Use ACME certificate managed by NixOS
|
|
||||||
tls ${serviceCfg.ssl.cert} ${serviceCfg.ssl.key}
|
|
||||||
|
|
||||||
# Compress responses
|
|
||||||
encode zstd gzip
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# MICROVM DEFINITION
|
|
||||||
# ============================================================================
|
|
||||||
# Everything below defines the VM's configuration
|
|
||||||
|
|
||||||
microvm.vms.${serviceCfg.name} = {
|
|
||||||
# VM Lifecycle
|
|
||||||
autostart = true; # Start VM automatically on host boot
|
|
||||||
restartIfChanged = true; # Restart VM when configuration changes
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────
|
|
||||||
# VM Guest Configuration
|
|
||||||
# ──────────────────────────────────────────────────────────────────────
|
|
||||||
# Everything inside 'config' runs INSIDE the VM
|
|
||||||
config = {
|
|
||||||
# NixOS version (should match host or be compatible)
|
|
||||||
system.stateVersion = "24.05";
|
|
||||||
|
|
||||||
# Timezone (should match host for consistent logging)
|
|
||||||
time.timeZone = "America/Winnipeg";
|
|
||||||
|
|
||||||
# SSH Access - allow SSH into VM using host user's keys
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = flake.config.people.users.${user0}.sshKeys;
|
|
||||||
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
# Services Configuration
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
services = {
|
|
||||||
# ══════════════════════════════════════════════════════════════════
|
|
||||||
# YOUR SERVICE CONFIGURATION GOES HERE
|
|
||||||
# ══════════════════════════════════════════════════════════════════
|
|
||||||
# Choose one of the patterns below based on your service type:
|
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────
|
|
||||||
# │ PATTERN 1: Simple Service (Vaultwarden-style)
|
|
||||||
# │ - Uses environment file for secrets
|
|
||||||
# │ - Single configuration block
|
|
||||||
# └─────────────────────────────────────────────────────────────────
|
|
||||||
# vaultwarden = {
|
|
||||||
# enable = true;
|
|
||||||
# dbBackend = "sqlite";
|
|
||||||
# config = {
|
|
||||||
# DOMAIN = "https://${host}";
|
|
||||||
#
|
|
||||||
# # Email Configuration
|
|
||||||
# SMTP_AUTH_MECHANISM = "Plain";
|
|
||||||
# SMTP_EMBED_IMAGES = true;
|
|
||||||
# SMTP_FROM = serviceCfg.email.address0;
|
|
||||||
# SMTP_FROM_NAME = serviceCfg.label;
|
|
||||||
# SMTP_HOST = smtpCfg.hostname;
|
|
||||||
# SMTP_PORT = smtpCfg.ports.port1;
|
|
||||||
# SMTP_SECURITY = smtpCfg.records.record1;
|
|
||||||
# SMTP_USERNAME = smtpCfg.email.address0;
|
|
||||||
#
|
|
||||||
# # Security Configuration
|
|
||||||
# DISABLE_ADMIN_TOKEN = false;
|
|
||||||
#
|
|
||||||
# # Web Server Settings
|
|
||||||
# ROCKET_ADDRESS = "0.0.0.0";
|
|
||||||
# ROCKET_PORT = serviceCfg.ports.port0;
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# # Mount secrets from host
|
|
||||||
# environmentFile = "/run/secrets/env";
|
|
||||||
# };
|
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────
|
|
||||||
# │ PATTERN 2: Complex Service (Forgejo-style)
|
|
||||||
# │ - Uses separate secret files
|
|
||||||
# │ - More complex settings structure
|
|
||||||
# └─────────────────────────────────────────────────────────────────
|
|
||||||
# forgejo = {
|
|
||||||
# enable = true;
|
|
||||||
# lfs.enable = true;
|
|
||||||
#
|
|
||||||
# # Separate secret files (not environment variables)
|
|
||||||
# secrets = {
|
|
||||||
# mailer.PASSWD = "/run/secrets/smtp";
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# dump = {
|
|
||||||
# interval = "5:00";
|
|
||||||
# type = "zip";
|
|
||||||
# file = "forgejo-backup";
|
|
||||||
# enable = true;
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# settings = {
|
|
||||||
# server = {
|
|
||||||
# DOMAIN = host;
|
|
||||||
# ROOT_URL = "https://${host}/";
|
|
||||||
# HTTP_PORT = serviceCfg.ports.port0;
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# service.DISABLE_REGISTRATION = true;
|
|
||||||
#
|
|
||||||
# actions = {
|
|
||||||
# ENABLED = true;
|
|
||||||
# DEFAULT_ACTIONS_URL = "github";
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# mirror = {
|
|
||||||
# ENABLED = true;
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# mailer = {
|
|
||||||
# ENABLED = true;
|
|
||||||
# SMTP_ADDR = smtpCfg.hostname;
|
|
||||||
# FROM = smtpCfg.email.address1;
|
|
||||||
# USER = smtpCfg.email.address1;
|
|
||||||
# PROTOCOL = "${smtpCfg.name}+${smtpCfg.records.record1}";
|
|
||||||
# SMTP_PORT = smtpCfg.ports.port1;
|
|
||||||
# SEND_AS_PLAIN_TEXT = true;
|
|
||||||
# USE_CLIENT_CERT = false;
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
# ┌─────────────────────────────────────────────────────────────────
|
|
||||||
# │ PATTERN 3: Media Service (Jellyfin-style)
|
|
||||||
# │ - Simple enable, uses openFirewall
|
|
||||||
# │ - No secrets needed
|
|
||||||
# └─────────────────────────────────────────────────────────────────
|
|
||||||
# jellyfin = {
|
|
||||||
# enable = true;
|
|
||||||
# openFirewall = true;
|
|
||||||
# };
|
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════════════════
|
|
||||||
# SSH Server (for VM management) - ALWAYS INCLUDE
|
|
||||||
# ══════════════════════════════════════════════════════════════════
|
|
||||||
openssh = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
PasswordAuthentication = false;
|
|
||||||
PermitRootLogin = "prohibit-password";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
# Firewall Configuration
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
# Open necessary ports inside the VM
|
|
||||||
#
|
|
||||||
# EXAMPLES:
|
|
||||||
# Vaultwarden: [22, 25, 139, 587, 2525, serviceCfg.ports.port0]
|
|
||||||
# Forgejo: [22, 25, 139, 587, 2525, serviceCfg.ports.port0]
|
|
||||||
# Jellyfin: [22, serviceCfg.ports.port0, port1, port2]
|
|
||||||
networking.firewall.allowedTCPPorts = [
|
|
||||||
22 # SSH (always include)
|
|
||||||
serviceCfg.ports.port0 # Main service port
|
|
||||||
|
|
||||||
# OPTIONAL: SMTP ports if service sends email
|
|
||||||
# 25 # SMTP
|
|
||||||
# 587 # SMTP Submission
|
|
||||||
# 2525 # Alternative SMTP
|
|
||||||
|
|
||||||
# OPTIONAL: Additional ports (like Jellyfin's discovery ports)
|
|
||||||
# serviceCfg.ports.port1
|
|
||||||
# serviceCfg.ports.port2
|
|
||||||
];
|
|
||||||
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
# OPTIONAL: Temporary Filesystem
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
# Some services need a large /tmp (e.g., Forgejo for large Git operations)
|
|
||||||
# Jellyfin also uses this pattern
|
|
||||||
#
|
|
||||||
# UNCOMMENT IF NEEDED:
|
|
||||||
# fileSystems."/tmp" = {
|
|
||||||
# device = "tmpfs";
|
|
||||||
# fsType = "tmpfs";
|
|
||||||
# options = [
|
|
||||||
# "size=4G" # Adjust size as needed
|
|
||||||
# "mode=1777" # Sticky bit for multi-user access
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
# Systemd Configuration
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
systemd = {
|
|
||||||
# Network Configuration (systemd-networkd)
|
|
||||||
# Configure the VM's network interface
|
|
||||||
#
|
|
||||||
# INTERFACE NAME: "enp0s5" is typical for QEMU with q35 machine
|
|
||||||
# To verify: SSH into VM and run: ip link show
|
|
||||||
network = {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
networks."20-lan" = {
|
|
||||||
# Match the network interface created by QEMU
|
|
||||||
matchConfig.Name = "enp0s5";
|
|
||||||
|
|
||||||
# Static IP Configuration
|
|
||||||
# MUST be on same subnet as host bridge (e.g., 192.168.50.0/24)
|
|
||||||
addresses = [
|
|
||||||
{ Address = "${serviceCfg.interface.ip}/24"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
# Default route for internet access
|
|
||||||
# PATTERN 1: Use "0.0.0.0/0" (Forgejo)
|
|
||||||
# PATTERN 2: Use "${hostCfg.localhost.address1}/0" (Vaultwarden, Jellyfin)
|
|
||||||
# Both work - choose one
|
|
||||||
routes = [
|
|
||||||
{
|
|
||||||
Destination = "0.0.0.0/0"; # or "${hostCfg.localhost.address1}/0"
|
|
||||||
Gateway = serviceCfg.interface.gate;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
# DNS servers
|
|
||||||
dns = [
|
|
||||||
"1.1.1.1" # Cloudflare
|
|
||||||
"8.8.8.8" # Google
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# OPTIONAL: VM-internal tmpfiles (Jellyfin and Forgejo use this)
|
|
||||||
# This creates directories INSIDE the VM, separate from host tmpfiles
|
|
||||||
# Used when the service needs specific ownership/permissions inside VM
|
|
||||||
#
|
|
||||||
# EXAMPLES:
|
|
||||||
# Jellyfin: "d ${serviceCfg.varPaths.path0}/media 0755 ${serviceCfg.name} ${serviceCfg.name} -"
|
|
||||||
# Forgejo: "d ${serviceCfg.varPaths.path0} 0755 ${serviceCfg.name} ${serviceCfg.name} -"
|
|
||||||
#
|
|
||||||
# UNCOMMENT IF NEEDED:
|
|
||||||
# tmpfiles.rules = [
|
|
||||||
# "d ${serviceCfg.varPaths.path0} 0755 ${serviceCfg.name} ${serviceCfg.name} -"
|
|
||||||
# ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Ensure systemd-networkd starts on boot
|
|
||||||
systemd.services.systemd-networkd.wantedBy = [ "multi-user.target" ];
|
|
||||||
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
# MicroVM Hardware Configuration
|
|
||||||
# ────────────────────────────────────────────────────────────────────
|
|
||||||
microvm = {
|
|
||||||
# Virtual CPU cores
|
|
||||||
# Adjust based on service needs:
|
|
||||||
# - Light services (Vaultwarden, Forgejo): 2 cores
|
|
||||||
# - Heavy services (Jellyfin): 6 cores
|
|
||||||
vcpu = 2;
|
|
||||||
|
|
||||||
# Memory in MB
|
|
||||||
# Adjust based on service needs:
|
|
||||||
# - Light services (Vaultwarden): 3072 MB (3 GB)
|
|
||||||
# - Medium services (Forgejo): 3072 MB (3 GB)
|
|
||||||
# - Heavy services (Jellyfin): 8192 MB (8 GB)
|
|
||||||
mem = 3072;
|
|
||||||
|
|
||||||
# Hypervisor - QEMU with KVM provides best performance
|
|
||||||
hypervisor = "qemu";
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────
|
|
||||||
# Network Interfaces
|
|
||||||
# ──────────────────────────────────────────────────────────────────
|
|
||||||
# All working configs use TWO interfaces: TAP + User-mode
|
|
||||||
interfaces = [
|
|
||||||
# Primary Interface: TAP (LAN Connectivity)
|
|
||||||
{
|
|
||||||
type = "tap";
|
|
||||||
id = serviceCfg.interface.id; # e.g., "vm-service"
|
|
||||||
mac = serviceCfg.interface.mac; # e.g., "02:00:00:00:00:51"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Secondary Interface: User-mode (NAT/Fallback)
|
|
||||||
{
|
|
||||||
type = "user";
|
|
||||||
id = serviceCfg.interface.idUser; # e.g., "vmuser-service"
|
|
||||||
mac = serviceCfg.interface.macUser; # e.g., "02:00:00:00:01:51"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────
|
|
||||||
# Port Forwarding (Host → VM)
|
|
||||||
# ──────────────────────────────────────────────────────────────────
|
|
||||||
# Forward SSH from host to VM for easy access
|
|
||||||
# Access via: ssh -p 22XX root@localhost (from host)
|
|
||||||
forwardPorts = [
|
|
||||||
{
|
|
||||||
from = "host";
|
|
||||||
host.port = serviceCfg.interface.ssh; # e.g., 2201
|
|
||||||
guest.port = 22;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────
|
|
||||||
# Shared Directories (VirtioFS)
|
|
||||||
# ──────────────────────────────────────────────────────────────────
|
|
||||||
# Share directories from host to VM
|
|
||||||
#
|
|
||||||
# IMPORTANT: All source paths must exist on host BEFORE VM starts
|
|
||||||
# Use systemd.tmpfiles.rules (in host section) to create directories
|
|
||||||
shares = [
|
|
||||||
# ┌───────────────────────────────────────────────────────────────
|
|
||||||
# │ Nix Store (Read-Only) - ALWAYS INCLUDE
|
|
||||||
# └───────────────────────────────────────────────────────────────
|
|
||||||
{
|
|
||||||
mountPoint = "/nix/.ro-store";
|
|
||||||
proto = "virtiofs";
|
|
||||||
source = "/nix/store";
|
|
||||||
tag = "read_only_nix_store";
|
|
||||||
}
|
|
||||||
|
|
||||||
# ┌───────────────────────────────────────────────────────────────
|
|
||||||
# │ Service Data (Read-Write)
|
|
||||||
# └───────────────────────────────────────────────────────────────
|
|
||||||
# CHOOSE ONE PATTERN:
|
|
||||||
#
|
|
||||||
# PATTERN 1: Direct path (Vaultwarden)
|
|
||||||
# {
|
|
||||||
# mountPoint = "/var/lib/bitwarden_rs";
|
|
||||||
# proto = "virtiofs";
|
|
||||||
# source = serviceCfg.mntPaths.path0;
|
|
||||||
# tag = "${serviceCfg.name}_data";
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# PATTERN 2: Use serviceCfg.name (Forgejo)
|
|
||||||
# {
|
|
||||||
# mountPoint = "/var/lib/${serviceCfg.name}";
|
|
||||||
# proto = "virtiofs";
|
|
||||||
# source = serviceCfg.mntPaths.path0;
|
|
||||||
# tag = "${serviceCfg.name}_data";
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# PATTERN 3: Use serviceCfg.varPaths (Jellyfin)
|
|
||||||
# {
|
|
||||||
# mountPoint = serviceCfg.varPaths.path0;
|
|
||||||
# proto = "virtiofs";
|
|
||||||
# source = serviceCfg.mntPaths.path0;
|
|
||||||
# tag = "${serviceCfg.name}_data";
|
|
||||||
# }
|
|
||||||
|
|
||||||
{
|
|
||||||
mountPoint = "/var/lib/${serviceCfg.name}"; # ADJUST THIS
|
|
||||||
proto = "virtiofs";
|
|
||||||
source = serviceCfg.mntPaths.path0;
|
|
||||||
tag = "${serviceCfg.name}_data";
|
|
||||||
}
|
|
||||||
|
|
||||||
# ┌───────────────────────────────────────────────────────────────
|
|
||||||
# │ OPTIONAL: Additional Data Mounts (like Jellyfin's cache)
|
|
||||||
# └───────────────────────────────────────────────────────────────
|
|
||||||
# UNCOMMENT IF NEEDED:
|
|
||||||
# {
|
|
||||||
# mountPoint = serviceCfg.varPaths.path1;
|
|
||||||
# proto = "virtiofs";
|
|
||||||
# source = "${serviceCfg.mntPaths.path0}/cache";
|
|
||||||
# tag = "${serviceCfg.name}_cache";
|
|
||||||
# }
|
|
||||||
|
|
||||||
# ┌───────────────────────────────────────────────────────────────
|
|
||||||
# │ Secrets (Read-Only) - INCLUDE IF SERVICE NEEDS SECRETS
|
|
||||||
# └───────────────────────────────────────────────────────────────
|
|
||||||
# CRITICAL: Source must use service-specific subdirectory!
|
|
||||||
# This matches the sops.secrets configuration above
|
|
||||||
#
|
|
||||||
# UNCOMMENT IF SERVICE NEEDS SECRETS:
|
|
||||||
# {
|
|
||||||
# mountPoint = "/run/secrets";
|
|
||||||
# proto = "virtiofs";
|
|
||||||
# source = "/run/secrets/${serviceCfg.name}";
|
|
||||||
# tag = "host_secrets";
|
|
||||||
# }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# QUICK REFERENCE: Pattern Comparison
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# ┌──────────────┬─────────────┬──────────────┬─────────────┐
|
|
||||||
# │ Aspect │ Vaultwarden │ Forgejo │ Jellyfin │
|
|
||||||
# ├──────────────┼─────────────┼──────────────┼─────────────┤
|
|
||||||
# │ vCPU │ 2 │ 2 │ 6 │
|
|
||||||
# │ Memory │ 3072 MB │ 3072 MB │ 8192 MB │
|
|
||||||
# │ Secrets │ env file │ sep. files │ none │
|
|
||||||
# │ /tmp mount │ no │ yes (4G) │ yes (4G) │
|
|
||||||
# │ VM tmpfiles │ no │ yes │ yes │
|
|
||||||
# │ Host perms │ 0777 │ 0777 │ 0777 │
|
|
||||||
# │ Data mounts │ 1 │ 1 │ 2 │
|
|
||||||
# │ Secrets mnt │ yes │ yes │ no │
|
|
||||||
# └──────────────┴─────────────┴──────────────┴─────────────┘
|
|
||||||
#
|
|
||||||
# ============================================================================
|
|
||||||
# CHECKLIST: Steps to Create New Service
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# 1. [ ] Copy this template to modules/nixos/services/YOUR-SERVICE/default.nix
|
|
||||||
# 2. [ ] Replace 'service' with your service name in instances reference
|
|
||||||
# 3. [ ] Uncomment and configure your service in services = { ... }
|
|
||||||
# 4. [ ] Adjust vcpu/mem based on service requirements
|
|
||||||
# 5. [ ] Configure secrets (if needed) - both sops.secrets and shares
|
|
||||||
# 6. [ ] Set correct mountPoint for service data (check service docs)
|
|
||||||
# 7. [ ] Adjust firewall ports based on service needs
|
|
||||||
# 8. [ ] Add /tmp mount if service needs large temporary space
|
|
||||||
# 9. [ ] Test build: sudo nixos-rebuild build --flake .#YOUR-HOST
|
|
||||||
# 10. [ ] Deploy: sudo nixos-rebuild switch --flake .#YOUR-HOST
|
|
||||||
# 11. [ ] Verify TAP exists: ip link show vm-YOUR-SERVICE
|
|
||||||
# 12. [ ] SSH to VM: ssh -p 22XX root@localhost
|
|
||||||
# 13. [ ] Check network in VM: ip addr show enp0s5
|
|
||||||
# 14. [ ] Test service: curl http://VM-IP:PORT
|
|
||||||
# 15. [ ] Test external access: https://YOUR-SERVICE.example.com
|
|
||||||
#
|
|
||||||
# ============================================================================
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue