Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
| b54be988cc |
139 changed files with 1216 additions and 1342 deletions
96
.sops.yaml
96
.sops.yaml
|
|
@ -1,96 +0,0 @@
|
||||||
keys:
|
|
||||||
- &admin_age_fi age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- &host_age_coturn age1vnrtarxwmqxflh2sxe2s49ldfzkve268hx62x4ltv38h3emv8dqspu028l
|
|
||||||
- &host_age_forgejo age1d5y8dx3e8pksvxr8fv8f02v0y7qg7kuwpxpmxksp7xlvrcpfju5sdz6guk
|
|
||||||
- &host_age_ikiwiki age1st5axcrn2s09effsjp6gl89rnwd967y007pzpzamlqydrpf7yeeqjwtnx0
|
|
||||||
- &host_age_jellyfin age10huhyn3va02zjysyanf8fd6lpfvjv3k3u6qymanz9jtcmfp3kqfskth7yt
|
|
||||||
- &host_age_keycloak age15kluaw2krucmc0j98zfk0s5tkwqer0ax6jva458zukzrgnqjqc9q7s88yd
|
|
||||||
- &host_age_lifeline age1pmx78vda0c2qnn8epvkavl26e2939uj65608fdq959ds60d58ucsqwxsua
|
|
||||||
- &host_age_mail-1 age1hny8kwx0uymselgas25q558ruxxdv7lgtu9d5rnd6x9w3nysk4zqumzzrp
|
|
||||||
- &host_age_mastodon age1r60mmmeulm33h0trc0y870dml5hzhglyjv4wecyjy2858pg8u47s793r30
|
|
||||||
- &host_age_matrix age1g60l5mu08xrwfw7uptwcwde8kp9dacs4ltqv2ndjskpy8z5sqakqssxxq5
|
|
||||||
- &host_age_metrics age1lrtengtdc0nzpagr8fkp5mwqda66jqr0s2h3wsxcdscmalp8n3js3r0e3n
|
|
||||||
- &host_age_metrics-nekomesh age1rh7zgp445t39c7tmh84r30e9edju8gmtn84u7rjwhmyntzkugucq5x0xse
|
|
||||||
- &host_age_nextcloud age1lvlmct30jtg7p4qpf8evtjlld6g74q2ckh803hd3ynr7cz7zlceq84flwu
|
|
||||||
- &host_age_searx age17h3js5v8s5vezcankky6kqxcrvtfxanmvhp3axmnqs4y9s2lr9yqvc6zrn
|
|
||||||
- &host_age_torrent age1m37wtvp7fpavaygn2jc6kq2gtuvgvf0jgwwhd3p5862djv5segqs97mg7c
|
|
||||||
- &host_age_valkyrie age1guqc5pnajp2whkla6vws4yqnpe5hq4z89w6te3n5yql5pugzfqlqczjlee
|
|
||||||
creation_rules:
|
|
||||||
- path_regex: config/hosts/coturn/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_coturn
|
|
||||||
- path_regex: config/hosts/forgejo/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_forgejo
|
|
||||||
- path_regex: config/hosts/ikiwiki/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_ikiwiki
|
|
||||||
- path_regex: config/hosts/jellyfin/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_jellyfin
|
|
||||||
- path_regex: config/hosts/keycloak/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_keycloak
|
|
||||||
- path_regex: config/hosts/lifeline/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_lifeline
|
|
||||||
- path_regex: config/hosts/mail-1/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_mail-1
|
|
||||||
- path_regex: config/hosts/mastodon/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_mastodon
|
|
||||||
- path_regex: config/hosts/matrix/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_matrix
|
|
||||||
- path_regex: config/hosts/metrics/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_metrics
|
|
||||||
- path_regex: config/hosts/metrics-nekomesh/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_metrics-nekomesh
|
|
||||||
- path_regex: config/hosts/nextcloud/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_nextcloud
|
|
||||||
- path_regex: config/hosts/searx/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_searx
|
|
||||||
- path_regex: config/hosts/torrent/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_torrent
|
|
||||||
- path_regex: config/hosts/valkyrie/.*
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin_age_fi
|
|
||||||
- *host_age_valkyrie
|
|
||||||
stores:
|
|
||||||
yaml:
|
|
||||||
indent: 2
|
|
||||||
|
|
@ -35,13 +35,13 @@
|
||||||
parted
|
parted
|
||||||
tmux
|
tmux
|
||||||
nano
|
nano
|
||||||
ssh-to-age
|
|
||||||
tcpdump
|
tcpdump
|
||||||
];
|
];
|
||||||
|
|
||||||
security.acme = {
|
security.acme = {
|
||||||
defaults.email = "acme@grzb.de";
|
defaults.email = "acme@grzb.de";
|
||||||
acceptTerms = true;
|
acceptTerms = true;
|
||||||
|
preliminarySelfsigned = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Print the ed25519 public ssh host key to console when booting
|
# Print the ed25519 public ssh host key to console when booting
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
min-port = 49200;
|
min-port = 49200;
|
||||||
max-port = 49500;
|
max-port = 49500;
|
||||||
use-auth-secret = true;
|
use-auth-secret = true;
|
||||||
static-auth-secret-file = "/run/secrets/static-auth-secret";
|
static-auth-secret-file = "/secrets/static-auth-secret.secret";
|
||||||
realm = "turn.nekover.se";
|
realm = "turn.nekover.se";
|
||||||
cert = "${config.security.acme.certs."turn.nekover.se".directory}/fullchain.pem";
|
cert = "${config.security.acme.certs."turn.nekover.se".directory}/fullchain.pem";
|
||||||
pkey = "${config.security.acme.certs."turn.nekover.se".directory}/key.pem";
|
pkey = "${config.security.acme.certs."turn.nekover.se".directory}/key.pem";
|
||||||
|
|
@ -42,11 +42,4 @@
|
||||||
total-quota=1200
|
total-quota=1200
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."static-auth-secret" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = "turnserver";
|
|
||||||
group = "turnserver";
|
|
||||||
restartUnits = [ "coturn.service" ];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,5 @@
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./acme.nix
|
./acme.nix
|
||||||
./coturn.nix
|
./coturn.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
config/hosts/coturn/secrets.nix
Normal file
11
config/hosts/coturn/secrets.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{ keyCommandEnv,... }:
|
||||||
|
{
|
||||||
|
deployment.keys."static-auth-secret.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "coturn/static-auth-secret" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "turnserver";
|
||||||
|
group = "turnserver";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
static-auth-secret: ENC[AES256_GCM,data:af5cjUSeiCEtYki85h+XoJW5FKY4X18i6zOBZnH64Ju/LwA/yUemA8co17TG5cQnc/sw1pz6LySL2DOq/Gj42g==,iv:Yne84/VLN0jCSulA5OQ0UKbQWkqWBmHYogDuAngAp48=,tag:wJ/4yGnbypjTo/akV3P9ZA==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLMXRScDR1NzhzZGRXYUZQ
|
|
||||||
ZGpRYUlOUWZTVHQvdUlrSG5SRWM2ME9sdUVZCldCZkZ0SXdqUjBVNlRnckg3N0dS
|
|
||||||
S0s2NkRnQys2SGJKSTdiUWlnbTg1dkEKLS0tIGthb0FESjAyMjlEbnV4S0lPOHda
|
|
||||||
S1ZBOWdTSmNRQXMvUGJnd05sK1Q2Qk0KHseEBDVLeSWHdgrYyITRuJyp3orrjwwS
|
|
||||||
04ORMniHR7ymHzRPvm3oX/jkFD0iJEmk8clgm/Gcn2AQ7xXeJO7Vnw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmemxWRnFLMFVEcVZCb3BT
|
|
||||||
MStWU21kcnF5enpleWt3dFdaMHo3RzJGaENNClU2M2tmdE0zd2pXWUJHQkV5Mkhi
|
|
||||||
a0lIbHJmWDN6UXhVeTZId3RhcEd5TWcKLS0tIFRlSUNQN0pGYmtiOGxJS0pJY0tQ
|
|
||||||
YjFzS205QklRZWdPbklIRzVzbFFPT2sKCXra+DUchbomy9pe2HJAbhAF1mstgUcv
|
|
||||||
NalettWmuLXe2B0WjC9fAy2AAJS6kysEbUh960suzSPLTqTce0MGfA==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1vnrtarxwmqxflh2sxe2s49ldfzkve268hx62x4ltv38h3emv8dqspu028l
|
|
||||||
lastmodified: "2026-05-16T23:13:15Z"
|
|
||||||
mac: ENC[AES256_GCM,data:PxX20JAaYhj3DE1KjakVmVucL7jjZU0vh5vnSNmKLgqedJiV2ZqEXpF4s1WPgYTY723aLiWDLw/8kTF/VmvMs8zOdGSkIhojWIWFE6I2yq1MjlawXuUhGpe6C1XGQ+w0KTqzyJLxyIsUSH24GqPHmLRMStE7bYdr0a4lRBHEyqE=,iv:6tXoqhG1XqDAz4SZSIxFCi01Be76/dV4vFPwv3lkcps=,tag:ytLoh7gJ+Iuqv5AwhDElrw==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.13.0
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,5 @@
|
||||||
./forgejo.nix
|
./forgejo.nix
|
||||||
./redis.nix
|
./redis.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
{ pkgs, ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
services.forgejo = {
|
services.forgejo = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.forgejo;
|
|
||||||
database.type = "postgres";
|
database.type = "postgres";
|
||||||
lfs.enable = true;
|
mailerPasswordFile = "/secrets/forgejo-mailer-password.secret";
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
DEFAULT = {
|
DEFAULT = {
|
||||||
|
|
@ -18,7 +17,6 @@
|
||||||
ROOT_URL = "https://git.nekover.se/";
|
ROOT_URL = "https://git.nekover.se/";
|
||||||
# LOCAL_ROOT_URL is apparently what Forgejo uses to access itself.
|
# LOCAL_ROOT_URL is apparently what Forgejo uses to access itself.
|
||||||
# Doesn't need to be set.
|
# Doesn't need to be set.
|
||||||
OFFLINE_MODE = true;
|
|
||||||
};
|
};
|
||||||
admin = {
|
admin = {
|
||||||
DISABLE_REGULAR_ORG_CREATION = false;
|
DISABLE_REGULAR_ORG_CREATION = false;
|
||||||
|
|
@ -36,10 +34,11 @@
|
||||||
DEFAULT_USER_VISIBILITY = "limited";
|
DEFAULT_USER_VISIBILITY = "limited";
|
||||||
DEFAULT_KEEP_EMAIL_PRIVATE = true;
|
DEFAULT_KEEP_EMAIL_PRIVATE = true;
|
||||||
ENABLE_BASIC_AUTHENTICATION = false;
|
ENABLE_BASIC_AUTHENTICATION = false;
|
||||||
ENABLE_NOTIFY_MAIL = true;
|
};
|
||||||
|
repo = {
|
||||||
|
DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
|
||||||
};
|
};
|
||||||
repository = {
|
repository = {
|
||||||
DEFAULT_REPO_UNITS = "repo.code";
|
|
||||||
ENABLE_PUSH_CREATE_USER = true;
|
ENABLE_PUSH_CREATE_USER = true;
|
||||||
ENABLE_PUSH_CREATE_ORG = true;
|
ENABLE_PUSH_CREATE_ORG = true;
|
||||||
};
|
};
|
||||||
|
|
@ -61,13 +60,5 @@
|
||||||
HOST = "redis+socket:///run/redis-forgejo/redis.sock";
|
HOST = "redis+socket:///run/redis-forgejo/redis.sock";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
secrets.mailer.PASSWD = "/run/secrets/forgejo-mailer-password";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."forgejo-mailer-password" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = "forgejo";
|
|
||||||
group = "forgejo";
|
|
||||||
restartUnits = [ "forgejo.service" ];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
set_real_ip_from 10.202.41.100;
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
real_ip_header proxy_protocol;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
||||||
13
config/hosts/forgejo/secrets.nix
Normal file
13
config/hosts/forgejo/secrets.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys = {
|
||||||
|
"forgejo-mailer-password.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "mail/forgejo-nekover-se" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "forgejo";
|
||||||
|
group = "forgejo";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
forgejo-mailer-password: ENC[AES256_GCM,data:bFUrFyE/reeTtKZCrb1T1CG8Ng9QbDwZo9AdxU67i8uNmKcn93k3dqY70tSqBTAc9hpsXyW3UTKnPpk+ffb0mw==,iv:p16td5KV0rTmrrtX8FMojotEa+2oiFmVizkc6mt9QyI=,tag:czg/IlNLkx75m2iSddUkUw==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFNjVaNlFWeG9vMW4vM2R3
|
|
||||||
bWQyVk9jN1VkUUczbTBzUmdpZ2NyWlV4aVFjCmZwa0lDcXUzVDM4d1Mwa1B4Qm9q
|
|
||||||
WjVKMXJBRVNtc0JzcmE0Y20zdCtzM3cKLS0tIEJWanpwZHdPMGJiL0lkME9yVGQ1
|
|
||||||
a3ZvRGV3VENIbmlubG16MWF3SkdyQ00KZj5vuzVyCqbLH5gnQjhRpOfHtIB3RVZC
|
|
||||||
m+VdnnAFIfShrxwfOekVavffaHmG3PWS7RUKoeZNSdtz1ScuwfazPw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYOEdadnQvSW1mcE9hSmFL
|
|
||||||
aFlqdHpTejNZRXJCbTh4WjQyQXVobitaa2hFCjV1RU9UOGlqaXhIckNLMmYwb0s2
|
|
||||||
eHY2VVpiQThzQUNuS1FLbFd3V2NGZk0KLS0tIGdOK3VEOUlNcldBQ1haRHhVS0cw
|
|
||||||
N3ZoNWlVK2trVkJLQlhnaHFueFdqVEkK800paYmP1opnW7o2V8f2zzWNR5tOVYGs
|
|
||||||
fl+SA7hE7uTpRrrGfuZq0jQgWOaeAbJ3+PzRuSrVlrXdWIyipcZM2Q==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1d5y8dx3e8pksvxr8fv8f02v0y7qg7kuwpxpmxksp7xlvrcpfju5sdz6guk
|
|
||||||
lastmodified: "2026-05-17T00:50:59Z"
|
|
||||||
mac: ENC[AES256_GCM,data:I3a9s9i6sFVTRQIAj94YZNyxQsDIWIvRhy9M/e6iMYpvoQyxFvMD3xAE0NQ1uX1QgMoi+6njTc8AmTXFJvSfoiqtVfHQH+HkLPMR27DZUY6kgZGMvUVswioSKfaF8fZxGEyWRPAuTDlynfOsGpr4Tqt5U8NBiYL1FDD6CPALaiY=,iv:RUbSPPTR6cTWwzvbnQRA/f9AjjjOpQUiEBrWvxqCpTQ=,tag:GcGsBgxWU/AXm06FkUI1LA==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.13.0
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
51
config/hosts/hydra/configuration.nix
Normal file
51
config/hosts/hydra/configuration.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
boot = {
|
||||||
|
loader.grub = {
|
||||||
|
enable = true;
|
||||||
|
device = "/dev/vda";
|
||||||
|
};
|
||||||
|
|
||||||
|
binfmt.emulatedSystems = [
|
||||||
|
"armv6l-linux"
|
||||||
|
"armv7l-linux"
|
||||||
|
"aarch64-linux"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
hostName = "hydra";
|
||||||
|
firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [ 8443 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.builder = {
|
||||||
|
isNormalUser = true;
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK/plZfxF/RtB+pJsUYx9HUgRcB56EoO0uj+j3AGzZta root@cherry"
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKeIiHkHA5c6/jZx+BB28c5wchdzlFI7R1gbvNmPyoOg root@kiara"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
nix = {
|
||||||
|
settings = {
|
||||||
|
trusted-users = [ "builder" ];
|
||||||
|
allowed-uris = "http:// https://";
|
||||||
|
};
|
||||||
|
buildMachines = [
|
||||||
|
{
|
||||||
|
hostName = "localhost";
|
||||||
|
systems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"armv6l-linux"
|
||||||
|
"armv7l-linux"
|
||||||
|
"aarch64-linux"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.05";
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,8 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./grafana.nix
|
./hydra.nix
|
||||||
./neo4j.nix
|
./nix-serve.nix
|
||||||
./prometheus.nix
|
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
14
config/hosts/hydra/hydra.nix
Normal file
14
config/hosts/hydra/hydra.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
services.hydra = {
|
||||||
|
enable = true;
|
||||||
|
hydraURL = "https://hydra.nekover.se";
|
||||||
|
listenHost = "localhost";
|
||||||
|
port = 3001;
|
||||||
|
useSubstitutes = true;
|
||||||
|
notificationSender = "hydra@robot.grzb.de";
|
||||||
|
extraConfig = "
|
||||||
|
binary_cache_public_uri = https://nix-cache.nekover.se
|
||||||
|
";
|
||||||
|
};
|
||||||
|
}
|
||||||
42
config/hosts/hydra/nginx.nix
Normal file
42
config/hosts/hydra/nginx.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"hydra.nekover.se" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
listen = [{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
}];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://localhost:3001";
|
||||||
|
};
|
||||||
|
extraConfig = ''
|
||||||
|
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
||||||
|
|
||||||
|
set_real_ip_from 10.202.41.100;
|
||||||
|
real_ip_header proxy_protocol;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
"nix-cache.nekover.se" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
listen = [ {
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
}];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://localhost:5005";
|
||||||
|
};
|
||||||
|
extraConfig = ''
|
||||||
|
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
||||||
|
|
||||||
|
set_real_ip_from 10.202.41.100;
|
||||||
|
real_ip_header proxy_protocol;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
9
config/hosts/hydra/nix-serve.nix
Normal file
9
config/hosts/hydra/nix-serve.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
services.nix-serve = {
|
||||||
|
enable = true;
|
||||||
|
port = 5005;
|
||||||
|
bindAddress = "localhost";
|
||||||
|
secretKeyFile = "/secrets/signing-key.secret";
|
||||||
|
};
|
||||||
|
}
|
||||||
11
config/hosts/hydra/secrets.nix
Normal file
11
config/hosts/hydra/secrets.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys."signing-key.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "hydra/signing-key" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "root";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,5 @@
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./ikiwiki.nix
|
./ikiwiki.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,4 +133,26 @@ in
|
||||||
"multi-user.target"
|
"multi-user.target"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services.ikiwiki-auth-setup = {
|
||||||
|
description = "Setup auth subdirectory for ikiwiki.cgi";
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
mkdir -p ${ikiwikiSettings.destdir}/auth
|
||||||
|
if [ ! -f ${ikiwikiSettings.cgi_wrapper} ${ikiwikiSettings.destdir}/auth/ikiwiki.cgi ]; then
|
||||||
|
ln -s ${ikiwikiSettings.cgi_wrapper} ${ikiwikiSettings.destdir}/auth/ikiwiki.cgi
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = config.users.users.ikiwiki.name;
|
||||||
|
Group = config.users.users.ikiwiki.group;
|
||||||
|
Requires = [ "ikiwiki-settings-setup.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
wantedBy = [
|
||||||
|
"multi-user.target"
|
||||||
|
];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ in
|
||||||
tryFiles = "$uri $uri/ =404";
|
tryFiles = "$uri $uri/ =404";
|
||||||
};
|
};
|
||||||
"~ .cgi" = {
|
"~ .cgi" = {
|
||||||
basicAuthFile = "/run/secrets/auth_file";
|
basicAuthFile = "/secrets/ikiwiki-auth-file.secret";
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
gzip off;
|
gzip off;
|
||||||
fastcgi_pass unix:${config.services.fcgiwrap.instances."ikiwiki".socket.address};
|
fastcgi_pass unix:${config.services.fcgiwrap.instances."ikiwiki".socket.address};
|
||||||
|
|
@ -39,17 +39,9 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
set_real_ip_from 10.202.41.100;
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
real_ip_header proxy_protocol;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."auth_file" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = "nginx";
|
|
||||||
group = "nginx";
|
|
||||||
restartUnits = [ "nginx.service" ];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
config/hosts/ikiwiki/secrets.nix
Normal file
11
config/hosts/ikiwiki/secrets.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys."ikiwiki-auth-file.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "ikiwiki/auth-file" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "nginx";
|
||||||
|
group = "nginx";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
auth_file: ENC[AES256_GCM,data:5/uT1sIOI95LNA9YFWh3I9J2PCZmz/J38YxVsKVWFHfJdZUOQpSW6ekjX7StP/svtv6Tp0AonnvcKfRcyPYn,iv:NKdWae+EihasTMV24Hk+dKJG8032mWu+RWItWs0b6RE=,tag:WBM6pXlKaDXOMnBWGBLJWg==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArNDZLcEFGRHczMHg3S0w3
|
|
||||||
eTNvNGI5TXBWTTc1eXAzZStlSmZTQ3NkdTA4CmlYVEF1NWhldVZuZmwzTUU0NG5j
|
|
||||||
UFhvU3Q3Q1BvVHhrODJWc296UUo0TmMKLS0tIFFlUGRYVDNNYm40cXhlZ004eFk5
|
|
||||||
b3BnLzBjZFpjVDN2clZaTGlWV29NVUEKsdK4V5Og+bK26Gl6HTkOBtFrHfr1RFYu
|
|
||||||
zWNGQ3skkvATO/ypa0zFf3+qnupCTTO5emwscoRK8ZZFVgSswdnbIA==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPOUJXWW95OXlEZFFwbHlp
|
|
||||||
RzJJMDFJU2pUTjltZ1JaWjE5c0xPY0hvNUdZCk5uWk9kdlRWNTNVUUVmT3VVeE9j
|
|
||||||
ajNNeVlZcEw4WFdqZ2QwTXl2MlhVZ2cKLS0tIFVVUXJtWkhtREFsdXp5ODZkOTA1
|
|
||||||
b1h3THFYSU1yblM0WmdxTUVtZG1OYVUK5tmcOX+jOdbSD1YCPqcAeoGF8ny61lWY
|
|
||||||
xwguejMeVZ/pCjO/qf3tb+MUlInPMXva59FelGd3nz6cbVqbeWtxSQ==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1st5axcrn2s09effsjp6gl89rnwd967y007pzpzamlqydrpf7yeeqjwtnx0
|
|
||||||
lastmodified: "2026-05-16T22:13:21Z"
|
|
||||||
mac: ENC[AES256_GCM,data:McAN1DueAhDBAY8kloB5l8M0pLIeswtnCxBtMYFyzBaY2Z43gNetBwdpzs5sL4nEmAZGPJ9AjXJVSmjb1tOn3BF8X5n6/9F7DzvHT7ukpIjumGC0KeB0QfaIGgKJyo7koISIVlGFZAwgcf1fQwaKZsYzfOGelj7UNrzFCjArK+Y=,iv:oZUmzcEr08jROw24J2fXQ4EjEJH3vzYysdy51vEtUNM=,tag:QJjNb/YvuZrZtQD9QE1Z3g==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.13.0
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,5 @@
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./jellyfin.nix
|
./jellyfin.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
fsType = "cifs";
|
fsType = "cifs";
|
||||||
options = [
|
options = [
|
||||||
"username=jellyfin"
|
"username=jellyfin"
|
||||||
"credentials=/run/secrets/samba-credentials"
|
"credentials=/secrets/samba-credentials.secret"
|
||||||
"iocharset=utf8"
|
"iocharset=utf8"
|
||||||
"vers=3.1.1"
|
"vers=3.1.1"
|
||||||
"uid=jellyfin"
|
"uid=jellyfin"
|
||||||
|
|
@ -13,10 +13,4 @@
|
||||||
"_netdev"
|
"_netdev"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."samba-credentials" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = "root";
|
|
||||||
group = "root";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
config/hosts/jellyfin/secrets.nix
Normal file
11
config/hosts/jellyfin/secrets.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys."samba-credentials.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "jellyfin/samba-credentials" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "root";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
samba-credentials: ENC[AES256_GCM,data:9txZMLLwlyAMzI3Naag3tUD1zSXLAf/zoJFoJZYTChhmkPpuhuuaIANFcYmH2sUYSsvZLXlbBuLXRryjTix0zK9ZfkZW8/R1vg==,iv:cF3S9S2+Vk+VAb8gyFyxZ12fqmohHSD3GG0fTILrxRM=,tag:m4BqpUlKmUoPbXTEjFmjaA==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzb3dQYWM4SHVraHFPZEx6
|
|
||||||
aGpDcTEyVjZ6Y0h6YzM4aVliRXpqZFpLcnprCmNEOHFrby9IdEE1MTZIYWxrS3BS
|
|
||||||
ZHZTSmYxUW9pek5XblIyZ2FDVlV0TEkKLS0tIEN6NnErRXI3ejc3cVBiSVR6NlpC
|
|
||||||
a2tnWWxDaXgwQ3hmc0dreTNIRnl0cTAKCSaj/epLw16tVDX4OMCzutxlnARL8MDf
|
|
||||||
pUVDonkZ7sB7d1+mnyG+gMQuFDhiDcV9WS2h3M83xoSKoHnCkca9Ew==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlbUdFMlZvVXlzc3FPSmE4
|
|
||||||
Rk1jeUpDVUJMeUlJZDlYeHhwK2l6UkJNRVFVCjNUVS9ZMjI2ME9qTFM0Umc3dXZC
|
|
||||||
Z0todzhYSXZ5Yk5odUdOZGg3VnE3QW8KLS0tIGd1emhUMFVHT3JiZ1JhY0FWOU1i
|
|
||||||
cW9PWk9oRHZGeFlSdlVLSlJ6TVg4WnMKikUhDJNyuKdiazCUcKBo834NO3U6ZfjB
|
|
||||||
GbDn3wUKb465CDYw7GPcvZtM2mNufsoInZh+Oq/07Hi+seAXfX2y7A==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age10huhyn3va02zjysyanf8fd6lpfvjv3k3u6qymanz9jtcmfp3kqfskth7yt
|
|
||||||
lastmodified: "2026-05-17T00:58:22Z"
|
|
||||||
mac: ENC[AES256_GCM,data:0WF8JU4d+5nHHB5iBmqdS6TkZem2AHrYNx6zDm4yoIKip7ZVTfCPCyhZ4c3QseEBn1G2IXsTMEtIk6RVI2JigSJPLjyXOTJOeWjVtPD5+1I+mrU7z+YWN+sK5i4F1hQX7/E4JbTDh/h+NbqZ6I9pBq7Nm12QUtZdp/7R5qChXs4=,iv:DBdSDx/X8fh7SXiC073AtDMPDB9idKItzEz2fl7xe+g=,tag:0O1pZp6+Y2Uf2DlijwZLeg==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.13.0
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
firewall = {
|
firewall = {
|
||||||
allowedTCPPorts = [ 80 443 ];
|
allowedTCPPorts = [ 80 443 ];
|
||||||
};
|
};
|
||||||
nameservers = [ "193.138.218.74" ];
|
|
||||||
extraHosts =
|
extraHosts =
|
||||||
''
|
''
|
||||||
10.202.46.101 jellyfin.grzb.de
|
10.202.46.101 jellyfin.grzb.de
|
||||||
|
|
@ -19,10 +18,5 @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
services.resolved = {
|
|
||||||
enable = true;
|
|
||||||
fallbackDns = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
system.stateVersion = "23.11";
|
system.stateVersion = "23.11";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,6 @@
|
||||||
{ pkgs, ... }:
|
{ ... }:
|
||||||
let
|
|
||||||
jellyseerrOverlay = final: prev: {
|
|
||||||
jellyseerr = prev.jellyseerr.overrideAttrs (finalAttr: previousAttr: {
|
|
||||||
dontCheckForBrokenSymlinks = true;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
pkgs-overlay = pkgs.extend jellyseerrOverlay;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
services.jellyseerr = {
|
services.jellyseerr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs-overlay.jellyseerr;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,5 @@
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./keycloak.nix
|
./keycloak.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,13 @@
|
||||||
services.keycloak = {
|
services.keycloak = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
hostname = "https://id.nekover.se";
|
hostname = "id.nekover.se";
|
||||||
hostname-admin = "https://keycloak-admin.nekover.se";
|
hostname-admin = "keycloak-admin.nekover.se";
|
||||||
proxy-headers = "xforwarded";
|
hostname-strict-backchannel = true;
|
||||||
http-enabled = true;
|
proxy = "edge";
|
||||||
http-host = "127.0.0.1";
|
http-host = "127.0.0.1";
|
||||||
http-port = 8080;
|
http-port = 8080;
|
||||||
};
|
};
|
||||||
database.passwordFile = "/run/secrets/keycloak-database-password";
|
database.passwordFile = "/secrets/keycloak-database-password.secret";
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."keycloak-database-password" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = "root";
|
|
||||||
group = "systemd-network";
|
|
||||||
restartUnits = [ "keycloak.service" ];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,7 @@
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
||||||
|
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
set_real_ip_from 10.202.41.100;
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
real_ip_header proxy_protocol;
|
||||||
|
|
||||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||||
|
|
@ -42,13 +41,6 @@
|
||||||
proxy_buffer_size 128k;
|
proxy_buffer_size 128k;
|
||||||
proxy_buffers 8 128k;
|
proxy_buffers 8 128k;
|
||||||
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Port 443;
|
|
||||||
# This is https in any case.
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
# Hide the X-Forwarded header.
|
# Hide the X-Forwarded header.
|
||||||
proxy_hide_header X-Forwarded;
|
proxy_hide_header X-Forwarded;
|
||||||
# Assume we are the only Reverse Proxy (well using Proxy Protocol, but that
|
# Assume we are the only Reverse Proxy (well using Proxy Protocol, but that
|
||||||
|
|
@ -104,13 +96,6 @@
|
||||||
proxy_buffer_size 128k;
|
proxy_buffer_size 128k;
|
||||||
proxy_buffers 8 128k;
|
proxy_buffers 8 128k;
|
||||||
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Port 443;
|
|
||||||
# This is https in any case.
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
# Hide the X-Forwarded header.
|
# Hide the X-Forwarded header.
|
||||||
proxy_hide_header X-Forwarded;
|
proxy_hide_header X-Forwarded;
|
||||||
# Assume we are the only Reverse Proxy (well using Proxy Protocol, but that
|
# Assume we are the only Reverse Proxy (well using Proxy Protocol, but that
|
||||||
|
|
|
||||||
13
config/hosts/keycloak/secrets.nix
Normal file
13
config/hosts/keycloak/secrets.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys = {
|
||||||
|
"keycloak-database-password.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "keycloak/database-password" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "systemd-network";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
keycloak-database-password: ENC[AES256_GCM,data:2Jk0wskmlpdpaZj05MX4YRRDR75eAkk5eDNNOTSA9+dN8OGkUWdI0CX9ZdQFUB31GiRaLZQ4I9gwnIc2sIxzuA==,iv:4fq+safzIGC21NFTaHsIfgZwuKelQyxttEeW7Pp09v8=,tag:c7LO34hJqi1yEwQ+cQc0Dg==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArR0Y2ZVg4S1FDYmRlS0xL
|
|
||||||
VWlJVzNvdHVXanBMN043QjcxVjd5bFk5d21JCnVzYVcwT2tnQS9jblhVQUFaNWZD
|
|
||||||
L0owQ1hhUFdhNVAzaVJNbWhQaEdXZlUKLS0tIFZFOFpKUklKNVJFRS9ZY1JaeS9D
|
|
||||||
RnF5YjRmbXRaY3h1MU5PWEZETGh0N2cKIwZg6mMY8c3VpE9hAk9bcFXLyzl7J/4M
|
|
||||||
BIh7C+yZbD7bL92TEP3gTpW+EsGiJl2LCq7NVVuDkboYuJ6kAqLppg==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGS25mcEErQ1pUMTV6U1h4
|
|
||||||
WXduajlyTFFncXdhZ09BdXg4amV4V0xMalFNCm85dk1ldUlHTytXRDJLcjIyN2M2
|
|
||||||
ZmVFVG1YcWhnTmwySmFRUDhEMkVyb1EKLS0tIHVDVkc3QytPU3pQTWxMSG1TRFdI
|
|
||||||
LzVUdGUrZmVTa1RqRHNWaFFhY09ySEUKFrN7X2ir3gwL/S91mychdjXi2oBPEPr9
|
|
||||||
aizXtIk0JX6SzrP/Oy0mYROeEEEUfPVBBypEUlBjlyeSyathmEoVLQ==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age15kluaw2krucmc0j98zfk0s5tkwqer0ax6jva458zukzrgnqjqc9q7s88yd
|
|
||||||
lastmodified: "2026-05-17T01:07:49Z"
|
|
||||||
mac: ENC[AES256_GCM,data:fAOsq2jrl8dTvQSn+Cp0sxuU5AuOdnm97LBIyPY71KbxMAY0vn/RDvhszvskMIE25JWGuZROnFoYmrkUqSp/pxG9gvcPQ6keW9WMr09YFli4u1tvADl6Ag+OkcgDe2UP1aPRkW6i7sGpq7Wfv/3G8HNMLgywhyiAA2XICymbDBI=,iv:ChOk26gheG2ErLVqt/rrMw1MxuOmEA595fay6pGUCcc=,tag:8wGA4YZa+ZyNDIBz/d1DUg==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.13.0
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
{
|
{
|
||||||
name = "mail-2";
|
name = "mail-2";
|
||||||
publicKey = "OIBOJlFzzM3P/u1ftVW2HWt8kA6NveB4PaBOIXhCYhM=";
|
publicKey = "OIBOJlFzzM3P/u1ftVW2HWt8kA6NveB4PaBOIXhCYhM=";
|
||||||
presharedKeyFile = "/run/secrets/wireguard-lifeline-mail-2-lifeline-psk";
|
presharedKeyFile = "/secrets/wireguard-lifeline-mail-2-lifeline-psk.secret";
|
||||||
allowedIPs = [ "172.18.50.2/32" ];
|
allowedIPs = [ "172.18.50.2/32" ];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
|
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
|
||||||
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 172.18.50.0/24 -o ens6 -j MASQUERADE
|
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 172.18.50.0/24 -o ens6 -j MASQUERADE
|
||||||
'';
|
'';
|
||||||
privateKeyFile = "/run/secrets/wireguard-lifeline-wg0-privatekey";
|
privateKeyFile = "/secrets/wireguard-lifeline-wg0-privatekey.secret";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
nat = {
|
nat = {
|
||||||
|
|
@ -62,19 +62,5 @@
|
||||||
|
|
||||||
services.prometheus.exporters.node.enable = false;
|
services.prometheus.exporters.node.enable = false;
|
||||||
|
|
||||||
sops.secrets."wireguard-lifeline-mail-2-lifeline-psk" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = "root";
|
|
||||||
group = "root";
|
|
||||||
restartUnits = [ "wireguard-wg0.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."wireguard-lifeline-wg0-privatekey" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = "root";
|
|
||||||
group = "root";
|
|
||||||
restartUnits = [ "wireguard-wg0.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
system.stateVersion = "23.05";
|
system.stateVersion = "23.05";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,5 @@
|
||||||
imports = [
|
imports = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
config/hosts/lifeline/secrets.nix
Normal file
21
config/hosts/lifeline/secrets.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys = {
|
||||||
|
"wireguard-lifeline-wg0-privatekey.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "wireguard/lifeline-wg0-privatekey" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "root";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
"wireguard-lifeline-mail-2-lifeline-psk.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "wireguard/lifeline-mail-2/psk" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "root";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
wireguard-lifeline-wg0-privatekey: ENC[AES256_GCM,data:yUIu+AC24/84w0GQPko64E89ZjzMoaa0Z8J2IFY8wDmCw+z1Als0h42XB5U=,iv:2pmy0FyeyvHbRRYnog9mth7hWfMt4mNe8/dSK3eYd2E=,tag:/gRbYT8EnbDRiFN0Ohu4ng==,type:str]
|
|
||||||
wireguard-lifeline-mail-2-lifeline-psk: ENC[AES256_GCM,data:IvgVTsgFfONCm3OJ8iKtwRUY6uTEZfpyGubm/iysOySebPuDg+/AGNUu5ZQ=,iv:HZpAqLLt/cDQo51+koS3nZ1mkN0ZmqCY7gedx6PHthM=,tag:klM8lxBmZvXn3XUD/duGMA==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLcGo4RTJsQnZWWXBadjAz
|
|
||||||
YW5VcFBwWUxUR2N2d092WmN6LzdkaStaVVNJCkdWLzF4ZU4rY3pPLzc1YUZUb2hM
|
|
||||||
bHNiRkhabG1ON2YzemdCMjQwOW5hdG8KLS0tIER4RGdZNkN4U0dTekx6MURpY0oz
|
|
||||||
ZURQbEF0c2VXNFFRVEI5YjUydzNQVTQK6Q3yE+P41Ukay2h2RVXHcCbE19piBwHa
|
|
||||||
Gdxok7ObnjTBpFxWuz4Sqvozb4R9dbkTPtSp72Yjv78QBinLmWGJ/A==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlemExaHpsTFBEYjJURjNp
|
|
||||||
WmluaHcwaUtyNmRINEJ6NXlFVWplZm9YeEJvCktMM2N0dWFxYUFKM25EdVo0RmNG
|
|
||||||
MDYzcFFnOG95SXdrU3VzWmdqQ3U0L2cKLS0tIGhHUmNNS0w0bzhhdHgzL1hYQjRr
|
|
||||||
SEczcDdWMnh3aThXK3JrLzkrTEZ0TkUKexB+HBUOWSsel9sNgUHnj5NJdj8zZX/C
|
|
||||||
XB4W6fwzMxPHHknk1y/4z/F8oNnUzXmh3QfT/15glDmmCpyM3PGWVw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1pmx78vda0c2qnn8epvkavl26e2939uj65608fdq959ds60d58ucsqwxsua
|
|
||||||
lastmodified: "2026-05-17T01:24:39Z"
|
|
||||||
mac: ENC[AES256_GCM,data:JyTfrwkD8GxbzzuK1CsBRr8+Hxheu1gvB2KP3jGJkvLktzzNLYH7qq7JJu2oP6X18MMa+dlMuY9lHosoWy+wA34kgrtBVqtCfTnOx3jafwfLdNVBVTORN8h7so1N0KKwuSJnFL6BqMWhiQiPVOENGThqlIqKDwSiP3hyfFLDBuM=,iv:0IkM76X2Ly3hil7XneURzQk4wVUJy/bs/9zX3r9cTVo=,tag:vC7HDnB6WCTTy5MSh4tDDg==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.13.0
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -15,20 +15,28 @@
|
||||||
];
|
];
|
||||||
routes = [
|
routes = [
|
||||||
{
|
{
|
||||||
|
routeConfig = {
|
||||||
Gateway = "10.202.41.1";
|
Gateway = "10.202.41.1";
|
||||||
Destination = "10.201.0.0/16";
|
Destination = "10.201.0.0/16";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
routeConfig = {
|
||||||
Gateway = "10.202.41.1";
|
Gateway = "10.202.41.1";
|
||||||
Destination = "10.202.0.0/16";
|
Destination = "10.202.0.0/16";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
routeConfig = {
|
||||||
Gateway = "10.202.41.1";
|
Gateway = "10.202.41.1";
|
||||||
Destination = "172.21.87.0/24";
|
Destination = "172.21.87.0/24";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
routeConfig = {
|
||||||
Gateway = "10.202.41.1";
|
Gateway = "10.202.41.1";
|
||||||
Destination = "212.53.203.19/32";
|
Destination = "212.53.203.19/32";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
linkConfig.RequiredForOnline = "routable";
|
linkConfig.RequiredForOnline = "routable";
|
||||||
|
|
@ -54,11 +62,13 @@
|
||||||
PrivateKeyFile = "/secrets/wireguard-mail-1-wg0-privatekey.secret";
|
PrivateKeyFile = "/secrets/wireguard-mail-1-wg0-privatekey.secret";
|
||||||
};
|
};
|
||||||
wireguardPeers = [{
|
wireguardPeers = [{
|
||||||
|
wireguardPeerConfig = {
|
||||||
PublicKey = "ik480irMZtGBs1AFpf1KGzDBekjdziD3ck7XK8r1WXQ=";
|
PublicKey = "ik480irMZtGBs1AFpf1KGzDBekjdziD3ck7XK8r1WXQ=";
|
||||||
PresharedKeyFile = "/secrets/wireguard-valkyrie-mail-1-mail-1-psk.secret";
|
PresharedKeyFile = "/secrets/wireguard-valkyrie-mail-1-mail-1-psk.secret";
|
||||||
Endpoint = "212.53.203.19:51822";
|
Endpoint = "212.53.203.19:51822";
|
||||||
AllowedIPs = [ "0.0.0.0/0" ];
|
AllowedIPs = [ "0.0.0.0/0" ];
|
||||||
PersistentKeepalive = 25;
|
PersistentKeepalive = 25;
|
||||||
|
};
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,5 @@
|
||||||
imports = [
|
imports = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./simple-nixos-mailserver.nix
|
./simple-nixos-mailserver.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,14 +73,6 @@
|
||||||
permissions = "0640";
|
permissions = "0640";
|
||||||
uploadAt = "pre-activation";
|
uploadAt = "pre-activation";
|
||||||
};
|
};
|
||||||
"mail-nekomesh-nekover-se.secret" = {
|
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "mail/nekomesh-nekover-se" ];
|
|
||||||
destDir = "/secrets";
|
|
||||||
user = "root";
|
|
||||||
group = "root";
|
|
||||||
permissions = "0640";
|
|
||||||
uploadAt = "pre-activation";
|
|
||||||
};
|
|
||||||
"mail-social-nekover-se.secret" = {
|
"mail-social-nekover-se.secret" = {
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "mail/social-nekover-se" ];
|
keyCommand = keyCommandEnv ++ [ "pass" "mail/social-nekover-se" ];
|
||||||
destDir = "/secrets";
|
destDir = "/secrets";
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
simple-nixos-mailserver.nixosModule {
|
simple-nixos-mailserver.nixosModule {
|
||||||
mailserver = {
|
mailserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
stateVersion = 3;
|
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
fqdn = "mail-1.grzb.de";
|
fqdn = "mail-1.grzb.de";
|
||||||
enableImap = false;
|
enableImap = false;
|
||||||
|
|
@ -47,11 +46,6 @@
|
||||||
sendOnly = true;
|
sendOnly = true;
|
||||||
aliases = [ "nyareply@nekover.se" ];
|
aliases = [ "nyareply@nekover.se" ];
|
||||||
};
|
};
|
||||||
"nekomesh@nekover.se" = {
|
|
||||||
hashedPasswordFile = "/secrets/mail-nekomesh-nekover-se.secret";
|
|
||||||
sendOnly = true;
|
|
||||||
aliases = [ "nyareply@nekover.se" ];
|
|
||||||
};
|
|
||||||
"social@nekover.se" = {
|
"social@nekover.se" = {
|
||||||
hashedPasswordFile = "/secrets/mail-social-nekover-se.secret";
|
hashedPasswordFile = "/secrets/mail-social-nekover-se.secret";
|
||||||
sendOnly = true;
|
sendOnly = true;
|
||||||
|
|
@ -75,8 +69,8 @@
|
||||||
|
|
||||||
services.postfix = {
|
services.postfix = {
|
||||||
transport = "relay:[mail-2.grzb.de]";
|
transport = "relay:[mail-2.grzb.de]";
|
||||||
settings.main = {
|
extraConfig = ''
|
||||||
proxy_interfaces = "212.53.203.19";
|
proxy_interfaces = 212.53.203.19
|
||||||
};
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
9
config/hosts/mail-2/acme.nix
Normal file
9
config/hosts/mail-2/acme.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
security.acme.certs = {
|
||||||
|
"mail-2.grzb.de" = {
|
||||||
|
listenHTTP = ":80";
|
||||||
|
reloadServices = [ "postfix.service" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
91
config/hosts/mail-2/configuration.nix
Normal file
91
config/hosts/mail-2/configuration.nix
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
boot.loader.grub = {
|
||||||
|
enable = true;
|
||||||
|
device = "/dev/vda";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.network = {
|
||||||
|
enable = true;
|
||||||
|
networks = {
|
||||||
|
"enp6s18" = {
|
||||||
|
matchConfig.Name = "enp6s18";
|
||||||
|
address = [
|
||||||
|
"10.201.41.100/24"
|
||||||
|
];
|
||||||
|
routes = [
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Gateway = "10.201.41.1";
|
||||||
|
Destination = "10.201.0.0/16";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Gateway = "10.201.41.1";
|
||||||
|
Destination = "10.202.0.0/16";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Gateway = "10.201.41.1";
|
||||||
|
Destination = "172.21.87.0/24";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Gateway = "10.201.41.1";
|
||||||
|
Destination = "217.160.117.160/32";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
linkConfig.RequiredForOnline = "routable";
|
||||||
|
};
|
||||||
|
"wg0" = {
|
||||||
|
matchConfig.Name = "wg0";
|
||||||
|
address = [
|
||||||
|
"172.18.50.2/24"
|
||||||
|
];
|
||||||
|
DHCP = "no";
|
||||||
|
gateway = [
|
||||||
|
"172.18.50.1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
netdevs = {
|
||||||
|
"wg0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = "wireguard";
|
||||||
|
Name = "wg0";
|
||||||
|
};
|
||||||
|
wireguardConfig = {
|
||||||
|
PrivateKeyFile = "/secrets/wireguard-mail-2-wg0-privatekey.secret";
|
||||||
|
};
|
||||||
|
wireguardPeers = [{
|
||||||
|
wireguardPeerConfig = {
|
||||||
|
PublicKey = "Nnf7x+Yd+l8ZkK2BTq1lK3iiTYgdrgL9PQ/je8smug4=";
|
||||||
|
PresharedKeyFile = "/secrets/wireguard-lifeline-mail-2-mail-2-psk.secret";
|
||||||
|
Endpoint = "217.160.117.160:51820";
|
||||||
|
AllowedIPs = [ "0.0.0.0/0" ];
|
||||||
|
PersistentKeepalive = 25;
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
hostName = "mail-2";
|
||||||
|
useDHCP = false;
|
||||||
|
firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [ 25 80 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
wireguard-tools
|
||||||
|
];
|
||||||
|
|
||||||
|
system.stateVersion = "23.05";
|
||||||
|
}
|
||||||
8
config/hosts/mail-2/default.nix
Normal file
8
config/hosts/mail-2/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./configuration.nix
|
||||||
|
./postfix.nix
|
||||||
|
./acme.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
37
config/hosts/mail-2/postfix.nix
Normal file
37
config/hosts/mail-2/postfix.nix
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
# Postfix relay configuration, see: https://www.postfix.org/STANDARD_CONFIGURATION_README.html#backup
|
||||||
|
services.postfix = {
|
||||||
|
enable = true;
|
||||||
|
hostname = "mail-2.grzb.de";
|
||||||
|
relayDomains = [
|
||||||
|
"grzb.de"
|
||||||
|
"nekover.se"
|
||||||
|
];
|
||||||
|
sslCert = "${config.security.acme.certs."mail-2.grzb.de".directory}/fullchain.pem";
|
||||||
|
sslKey = "${config.security.acme.certs."mail-2.grzb.de".directory}/key.pem";
|
||||||
|
extraConfig = ''
|
||||||
|
message_size_limit = 20971520
|
||||||
|
smtpd_relay_restrictions = permit_mynetworks reject_unauth_destination
|
||||||
|
proxy_interfaces = 217.160.117.160
|
||||||
|
relay_recipient_maps =
|
||||||
|
smtp_tls_ciphers = high
|
||||||
|
smtp_tls_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
|
||||||
|
smtp_tls_mandatory_ciphers = high
|
||||||
|
smtp_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
|
||||||
|
smtp_tls_mandatory_protocols = TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
|
||||||
|
smtp_tls_protocols = TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
|
||||||
|
smtpd_tls_auth_only = yes
|
||||||
|
smtpd_tls_ciphers = high
|
||||||
|
smtpd_tls_eecdh_grade = ultra
|
||||||
|
smtpd_tls_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
|
||||||
|
smtpd_tls_loglevel = 1
|
||||||
|
smtpd_tls_mandatory_ciphers = high
|
||||||
|
smtpd_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
|
||||||
|
smtpd_tls_mandatory_protocols = TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
|
||||||
|
smtpd_tls_protocols = TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
|
||||||
|
tls_preempt_cipherlist = yes
|
||||||
|
tls_random_source = dev:/dev/urandom
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
21
config/hosts/mail-2/secrets.nix
Normal file
21
config/hosts/mail-2/secrets.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys = {
|
||||||
|
"wireguard-mail-2-wg0-privatekey.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "wireguard/mail-2-wg0-privatekey" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "systemd-network";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
"wireguard-lifeline-mail-2-mail-2-psk.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "wireguard/lifeline-mail-2/psk" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "systemd-network";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
23
config/hosts/mastodon/containers/fedifetcher/default.nix
Normal file
23
config/hosts/mastodon/containers/fedifetcher/default.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{ nixpkgs-unstable, ... }:
|
||||||
|
{
|
||||||
|
containers.fedifetcher = {
|
||||||
|
nixpkgs = nixpkgs-unstable;
|
||||||
|
autoStart = true;
|
||||||
|
|
||||||
|
bindMounts = {
|
||||||
|
"/secrets" = {
|
||||||
|
hostPath = "/secrets-fedifetcher";
|
||||||
|
isReadOnly = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = { ... }: {
|
||||||
|
imports = [
|
||||||
|
./fedifetcher.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.useHostResolvConf = true;
|
||||||
|
system.stateVersion = "24.05";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
42
config/hosts/mastodon/containers/fedifetcher/fedifetcher.nix
Normal file
42
config/hosts/mastodon/containers/fedifetcher/fedifetcher.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
{
|
||||||
|
# config copied from https://github.com/arachnist/nibylandia/blob/main/nixos/zorigami/default.nix
|
||||||
|
systemd.services.fedifetcher = {
|
||||||
|
path = [ pkgs.fedifetcher ];
|
||||||
|
description = "fetch fedi posts";
|
||||||
|
script = ''
|
||||||
|
fedifetcher
|
||||||
|
'';
|
||||||
|
environment = lib.mapAttrs' (n: v:
|
||||||
|
(lib.nameValuePair ("ff_" + builtins.replaceStrings [ "-" ] [ "_" ] n)
|
||||||
|
(builtins.toString v))) {
|
||||||
|
server = "social.nekover.se";
|
||||||
|
state-dir = "/var/lib/fedifetcher";
|
||||||
|
lock-file = "/run/fedifetcher/fedifetcher.lock";
|
||||||
|
from-lists = 1;
|
||||||
|
from-notifications = 1;
|
||||||
|
max-bookmarks = 80;
|
||||||
|
max-favourites = 40;
|
||||||
|
max-follow-requests = 80;
|
||||||
|
max-followers = 80;
|
||||||
|
max-followings = 80;
|
||||||
|
remember-hosts-for-days = 30;
|
||||||
|
remember-users-for-hours = 168;
|
||||||
|
reply-interval-in-hours = 2;
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = true;
|
||||||
|
User = "fedifetcher";
|
||||||
|
RuntimeDirectory = "fedifetcher";
|
||||||
|
RuntimeDirectoryPreserve = true;
|
||||||
|
StateDirectory = "fedifetcher";
|
||||||
|
UMask = "0077";
|
||||||
|
EnvironmentFile = [ "/secrets/mastodon-fedifetcher-access-token.secret" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.timers.fedifetcher = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
timerConfig = { OnCalendar = "*:0/5"; };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
./mastodon.nix
|
./mastodon.nix
|
||||||
./opensearch.nix
|
./opensearch.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
./containers/fedifetcher
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,35 @@
|
||||||
{ pkgs, nixpkgs-unstable, ... }:
|
{ pkgs, ... }:
|
||||||
let
|
let
|
||||||
tangerineUI = pkgs.fetchgit {
|
tangerineUI = pkgs.fetchgit {
|
||||||
url = "https://github.com/nileane/TangerineUI-for-Mastodon.git";
|
url = "https://github.com/nileane/TangerineUI-for-Mastodon.git";
|
||||||
rev = "v2.5.3";
|
rev = "v2.2";
|
||||||
hash = "sha256-fs/pwIwXZvSNVmlSG304CMT/hSW/RtrzraMsrhg/TbE=";
|
hash = "sha256-KyXDnpZh1DrY59jvdU42UicgBVvEGtvAGeU1mNxJauQ=";
|
||||||
};
|
|
||||||
mastodonModern = pkgs.fetchgit {
|
|
||||||
url = "https://git.gay/freeplay/Mastodon-Modern.git";
|
|
||||||
rev = "f899b68740e25e17ed600e38657d0ef94c92b293";
|
|
||||||
hash = "sha256-+HQ7+Ypv540qB7ACfROJs8JUuqvMzaveKOdBsAfr3D4=";
|
|
||||||
};
|
};
|
||||||
mastodonNekoversePatches = pkgs.fetchgit {
|
mastodonNekoversePatches = pkgs.fetchgit {
|
||||||
url = "https://github.com/yuri-qq/nekoverse-mastodon-patches.git";
|
url = "https://github.com/yuri-qq/nekoverse-mastodon-patches.git";
|
||||||
hash = "sha256-NtdJWMi8/siduX2iFD+GAsK9J+Y6T/tZ/fXqb/QH284=";
|
hash = "sha256-3jWbKll5RGB1vfEmONVivzGYcoONEkBEHh/rOt9LXlU=";
|
||||||
};
|
};
|
||||||
mastodonNekoverseOverlay = final: prev: {
|
mastodonNekoverseOverlay = final: prev: {
|
||||||
mastodon = (prev.mastodon.override rec {
|
mastodon = (prev.mastodon.override rec {
|
||||||
version = "4.5.9";
|
version = "4.3.1";
|
||||||
srcOverride = final.applyPatches {
|
srcOverride = final.applyPatches {
|
||||||
src = pkgs.stdenv.mkDerivation {
|
src = pkgs.stdenv.mkDerivation {
|
||||||
name = "mastodonWithThemes";
|
name = "mastodonWithThemes";
|
||||||
src = pkgs.fetchgit {
|
src = pkgs.fetchgit {
|
||||||
url = "https://github.com/mastodon/mastodon.git";
|
url = "https://github.com/mastodon/mastodon.git";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "sha256-EXMJWdcuvQWe2cXONlcN/oB4b0nXwDqRT+miIB7P7js=";
|
sha256 = "sha256-JlpQGyVPTLcB3RcWMBrmYc1AAUT1JLfS4IDas9ZoWh4=";
|
||||||
};
|
};
|
||||||
# mastodon ships with broken symlinks, disable the check for that for now
|
|
||||||
dontCheckForBrokenSymlinks = true;
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
cp -r ./ $out/
|
cp -r ./ $out/
|
||||||
cp -r ${tangerineUI}/mastodon/app/javascript/styles/* $out/app/javascript/styles/
|
cp -r ${tangerineUI}/mastodon/app/javascript/styles/* $out/app/javascript/styles/
|
||||||
echo "@import 'mastodon/variables';
|
|
||||||
@import 'application';" >> $out/app/javascript/styles/modern-dark.scss
|
|
||||||
cat ${mastodonModern}/modern.css >> $out/app/javascript/styles/modern-dark.scss
|
|
||||||
echo "tangerineui: styles/tangerineui.scss
|
echo "tangerineui: styles/tangerineui.scss
|
||||||
tangerineui-purple: styles/tangerineui-purple.scss
|
tangerineui-purple: styles/tangerineui-purple.scss
|
||||||
tangerineui-cherry: styles/tangerineui-cherry.scss
|
tangerineui-cherry: styles/tangerineui-cherry.scss
|
||||||
tangerineui-lagoon: styles/tangerineui-lagoon.scss
|
tangerineui-lagoon: styles/tangerineui-lagoon.scss" >> $out/config/themes.yml
|
||||||
modern-dark: styles/modern-dark.scss" >> $out/config/themes.yml
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
patches = prev.mastodon.src.patches ++ [
|
patches = [
|
||||||
"${mastodonNekoversePatches}/patches/001_increase_image_dimensions_limit.patch"
|
"${mastodonNekoversePatches}/patches/001_increase_image_dimensions_limit.patch"
|
||||||
"${mastodonNekoversePatches}/patches/002_disable_image_reprocessing.patch"
|
"${mastodonNekoversePatches}/patches/002_disable_image_reprocessing.patch"
|
||||||
"${mastodonNekoversePatches}/patches/003_make_toot_cute.patch"
|
"${mastodonNekoversePatches}/patches/003_make_toot_cute.patch"
|
||||||
|
|
@ -49,8 +38,7 @@ let
|
||||||
"${mastodonNekoversePatches}/patches/006_increase_toot_character_limit.patch"
|
"${mastodonNekoversePatches}/patches/006_increase_toot_character_limit.patch"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
yarnHash = prev.mastodon.src.yarnHash;
|
yarnHash = "sha256-e5c04M6XplAgaVyldU5HmYMYtY3MAWs+a8Z/BGSyGBg=";
|
||||||
yarnMissingHashes = prev.mastodon.src.yarnMissingHashes;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
pkgs-overlay = pkgs.extend mastodonNekoverseOverlay;
|
pkgs-overlay = pkgs.extend mastodonNekoverseOverlay;
|
||||||
|
|
@ -62,6 +50,7 @@ in
|
||||||
package = pkgs-overlay.mastodon;
|
package = pkgs-overlay.mastodon;
|
||||||
localDomain = "social.nekover.se";
|
localDomain = "social.nekover.se";
|
||||||
secretKeyBaseFile = "/secrets/mastodon-secret-key-base.secret";
|
secretKeyBaseFile = "/secrets/mastodon-secret-key-base.secret";
|
||||||
|
otpSecretFile = "/secrets/mastodon-otp-secret.secret";
|
||||||
vapidPublicKeyFile = "${vapidPublicKey}";
|
vapidPublicKeyFile = "${vapidPublicKey}";
|
||||||
vapidPrivateKeyFile = "/secrets/mastodon-vapid-private-key.secret";
|
vapidPrivateKeyFile = "/secrets/mastodon-vapid-private-key.secret";
|
||||||
smtp = {
|
smtp = {
|
||||||
|
|
@ -90,8 +79,6 @@ in
|
||||||
OIDC_REDIRECT_URI = "https://social.nekover.se/auth/auth/openid_connect/callback";
|
OIDC_REDIRECT_URI = "https://social.nekover.se/auth/auth/openid_connect/callback";
|
||||||
OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED = "true";
|
OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED = "true";
|
||||||
OIDC_END_SESSION_ENDPOINT = "https://id.nekover.se/realms/nekoverse/protocol/openid-connect/logout";
|
OIDC_END_SESSION_ENDPOINT = "https://id.nekover.se/realms/nekoverse/protocol/openid-connect/logout";
|
||||||
FETCH_REPLIES_ENABLED = "true";
|
|
||||||
AUTHORIZED_FETCH = "true";
|
|
||||||
};
|
};
|
||||||
extraEnvFiles = [
|
extraEnvFiles = [
|
||||||
"/secrets/mastodon-keycloak-client-secret.secret"
|
"/secrets/mastodon-keycloak-client-secret.secret"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
group = "mastodon";
|
group = "mastodon";
|
||||||
clientMaxBodySize = "200m";
|
|
||||||
upstreams.streaming = {
|
upstreams.streaming = {
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
least_conn;
|
least_conn;
|
||||||
|
|
@ -57,8 +56,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
set_real_ip_from 10.202.41.100;
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
real_ip_header proxy_protocol;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,14 @@
|
||||||
permissions = "0640";
|
permissions = "0640";
|
||||||
uploadAt = "pre-activation";
|
uploadAt = "pre-activation";
|
||||||
};
|
};
|
||||||
|
"mastodon-otp-secret.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "mastodon/otp-secret" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "mastodon";
|
||||||
|
group = "mastodon";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
"mastodon-vapid-private-key.secret" = {
|
"mastodon-vapid-private-key.secret" = {
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "mastodon/vapid-private-key" ];
|
keyCommand = keyCommandEnv ++ [ "pass" "mastodon/vapid-private-key" ];
|
||||||
destDir = "/secrets";
|
destDir = "/secrets";
|
||||||
|
|
@ -57,5 +65,13 @@
|
||||||
permissions = "0640";
|
permissions = "0640";
|
||||||
uploadAt = "pre-activation";
|
uploadAt = "pre-activation";
|
||||||
};
|
};
|
||||||
|
"mastodon-fedifetcher-access-token.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "mastodon/fedifetcher-access-token" ];
|
||||||
|
destDir = "/secrets-fedifetcher";
|
||||||
|
user = "root";
|
||||||
|
group = "root";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
mastodon-secret-key-base: ENC[AES256_GCM,data:GP8mtL5hkDqNjbiqONXJNDX+e9RuOejnAxX0fk1gvVR+Xkb99/wNPun1p85AVOv1rn8n0H4X8aZwPK/P2lljyGWs4RSwYaLOMMoowSu+QwDYzK2+uf2lsiM5esOAr/rfuX1BZIEnrJPYAIZYtTIBTyrMN9zTtPvyBaPn4cL0sKQ=,iv:jxy37Sa3ywLhVSYhgiC1spky6psxZzso74es5CnBObw=,tag:+nW6SxoYJgcSU2r6d2J00g==,type:str]
|
|
||||||
mastodon-vapid-private-key: ENC[AES256_GCM,data:mE29UuQGzQ/LPrvop0zODM3tI/DOXsCPemh/5Y7VribAUq25Fftoo3tWEbk=,iv:qJTJL4g9AOcPJIP9IWnSso6ECs3sSiubW9SNUaYIcXE=,tag:OnhsJeWYLDFMlmVsLf4syw==,type:str]
|
|
||||||
mastodon-email-smtp-pass: ENC[AES256_GCM,data:8UcjUSZMuUPZvc1hM79XGjor0LuKcGg8qLr/oFggcTMtQ9+ff2QHGaZFiHRcNFibdp0IexO2PDy0yMF5qivxJA==,iv:fd3vv21PnC2M/Ptdwy2j6vn+juWrEnZKtTtzhS71igI=,tag:8nmdu2TD0TTmCfA+kIkb4Q==,type:str]
|
|
||||||
mastodon-keycloak-client-secret: ENC[AES256_GCM,data:jLDVhGhUUI5o2UjHolahncXXiqHHyFT/SavQTaUTlaSje3l2khvAIzmEn8TfC6FrF8BMjzI=,iv:Hq5XrtpnFYnIxrIb8rX5PDL7z7bLuOrtTTubm7HsE88=,tag:ayNJWs3UROd/sBQ5rnuv6w==,type:str]
|
|
||||||
mastodon-active-record-encryption-primary-key: ENC[AES256_GCM,data:H45LQ1gXCaepRe1ftap5ruWwC7ThI8m/EBtKdqP8QHQ=,iv:wAYQW7INq36GscjdaldCCS0RpjYuemtveoNdeqS1wz0=,tag:hjlXqo9WmE57fENQZaRCXA==,type:str]
|
|
||||||
mastodon-active-record-encryption-key-derivation-salt: ENC[AES256_GCM,data:DeeXCelirIcDyTDdPeKoaAeD2jzWGLU3p28e5JX8m9E=,iv:yQcddWeesrMWgIAj/MnBwPUwikk2VHAbNDFs0r5Fp0Q=,tag:H6boQ5IEGEhx5Ha15eEUhw==,type:str]
|
|
||||||
mastodon-active-record-encryption-deterministic-key: ENC[AES256_GCM,data:yrakH+MxQ8/SmAtLOvGcyIAjfbVdb8NgqYqpm+ALKA0=,iv:ZbagvnAPTLBmzxAdXZ0Ecat0jTpeRWiudpk3U+1hEXE=,tag:pnF87Gg4nTRC1YVK1bbGCw==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuTDB3d1FFWjY2LzhZUmVP
|
|
||||||
S1BicjRhc2ZzWWMvb2xjT1lzVVY3Z2hqYW53CndNaGJ6NXkyamg0a1BIdzlVL214
|
|
||||||
dk5SbDFDdVNGNnp1citjZkQ3UTNHcUUKLS0tIGwvOHl4RUErRjR3Nm1paGVmZEhX
|
|
||||||
a1N2SlZlY05aN2hEcXlGdnA0ZndlUjgK01enGoJvkN5YMbm38wcRYaM1ogzybJIL
|
|
||||||
OTig1Fg2CopEmaE/Y6bpuMFIyCFXZDhJQ3LaI+0kydzPGB2nZyWZ2g==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1tf38ae8yzzzmtjp5cjyemf0a8cksq62dz0x0hsntyhsjk5pq6s6q3v9nm7
|
|
||||||
- enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtbnFPOEJVWXAxTEpiNUgw
|
|
||||||
SDliL3hZeWpaK3JMN0hyV09jUTBSV2pYN2gwCmd2STBsYzhNYlpWRzhCUWZhZ1Rw
|
|
||||||
Yzdta25vN0NKeTFXWXRiUWZsTGVaY28KLS0tIC8yUERNWHNqTTFQazQzRkYvNk9K
|
|
||||||
TjlQaVRFdXJ6WVRIVnczYmlFc2t6S2MK5wnjZnhL+GK1eXnANSDe5zcsZdb5N715
|
|
||||||
odb/rjaIvUKaSUkmJfQK954pCBsiJXnURt5FKLnOGHtlQmt0kyg8dQ==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
recipient: age1r60mmmeulm33h0trc0y870dml5hzhglyjv4wecyjy2858pg8u47s793r30
|
|
||||||
lastmodified: "2026-05-17T01:44:58Z"
|
|
||||||
mac: ENC[AES256_GCM,data:DV91qRrbXxS+yvknPuLjRWYdsJdWtODy9q2onrSpWv6P7YR1siNFNpDyioMLKLRby80kY1R1zSofiaepVmP/nWtqtSDsq/plNWIZi7FR7X0TG0hNc3S6GJ0UatXVxOGp6LxvO2doVIMUs3LKd4+16FFMQYEQJ35VbuYFVhWw5SU=,iv:zVmZ7Ho28I9y7IvCULWehzJB64FSLLaspa/Rj+EJpX0=,tag:HRBTVgvm8pZvUgFBqjCEoQ==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.13.0
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
hostName = "matrix";
|
hostName = "matrix";
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowedTCPPorts = [ 80 8443 8448 9000 ];
|
allowedTCPPorts = [ 80 8443 8448 ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,9 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./element-call.nix
|
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./postgresql.nix
|
./postgresql.nix
|
||||||
./matrix-authentication-service.nix
|
|
||||||
./matrix-synapse.nix
|
./matrix-synapse.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
services.livekit = {
|
|
||||||
enable = true;
|
|
||||||
settings.rtc.use_external_ip = true;
|
|
||||||
openFirewall = true;
|
|
||||||
keyFile = "/secrets/matrix-livekit-secret-key.secret";
|
|
||||||
};
|
|
||||||
services.lk-jwt-service = {
|
|
||||||
enable = true;
|
|
||||||
port = 8082;
|
|
||||||
livekitUrl = "wss://matrix-rtc.nekover.se/livekit/sfu";
|
|
||||||
keyFile = "/secrets/matrix-livekit-secret-key.secret";
|
|
||||||
};
|
|
||||||
systemd.services.lk-jwt-service.environment = {
|
|
||||||
LIVEKIT_FULL_ACCESS_HOMESERVERS = "nekover.se";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
masSettings = {
|
|
||||||
http = {
|
|
||||||
listeners = [
|
|
||||||
{
|
|
||||||
name = "web";
|
|
||||||
resources = [
|
|
||||||
{ name = "discovery"; }
|
|
||||||
{ name = "human"; }
|
|
||||||
{ name = "oauth"; }
|
|
||||||
{ name = "compat"; }
|
|
||||||
{ name = "graphql"; }
|
|
||||||
{
|
|
||||||
name = "assets";
|
|
||||||
path = "${pkgs.matrix-authentication-service}/share/matrix-authentication-service/assets/";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
binds = [{
|
|
||||||
host = "localhost";
|
|
||||||
port = 8080;
|
|
||||||
}];
|
|
||||||
proxy_protocol = false;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "internal";
|
|
||||||
resources = [{
|
|
||||||
name = "health";
|
|
||||||
}];
|
|
||||||
binds = [{
|
|
||||||
host = "localhost";
|
|
||||||
port = 8081;
|
|
||||||
}];
|
|
||||||
proxy_protocol = false;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "admin";
|
|
||||||
resources = [{
|
|
||||||
name = "adminapi";
|
|
||||||
}];
|
|
||||||
binds = [{
|
|
||||||
host = "localhost";
|
|
||||||
port = 8083;
|
|
||||||
}];
|
|
||||||
proxy_protocol = false;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
trusted_proxies = [
|
|
||||||
"192.168.0.0/16"
|
|
||||||
"172.16.0.0/12"
|
|
||||||
"10.0.0.0/10"
|
|
||||||
"127.0.0.1/8"
|
|
||||||
"fd00::/8"
|
|
||||||
"::1/128"
|
|
||||||
];
|
|
||||||
public_base = "https://mas.nekover.se";
|
|
||||||
};
|
|
||||||
database = {
|
|
||||||
uri = "postgresql://mas_user:mas@localhost/mas";
|
|
||||||
max_connections = 10;
|
|
||||||
min_connections = 0;
|
|
||||||
connect_timeout = 30;
|
|
||||||
idle_timeout = 600;
|
|
||||||
max_lifetime = 1800;
|
|
||||||
};
|
|
||||||
passwords = {
|
|
||||||
enabled = true;
|
|
||||||
schemes = [
|
|
||||||
{
|
|
||||||
version = 1;
|
|
||||||
algorithm = "bcrypt";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
version = 2;
|
|
||||||
algorithm = "argon2id";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
masSettingsFile = ((pkgs.formats.yaml { }).generate "mas-config" masSettings);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
matrix-authentication-service
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services.matrix-authentication-service = {
|
|
||||||
description = "Matrix Authentication Service";
|
|
||||||
after = [ "network-online.target" "postgresql.service" ];
|
|
||||||
requires = [ "postgresql.service" ];
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
|
||||||
ExecStart = "${pkgs.matrix-authentication-service}/bin/mas-cli server --config=${masSettingsFile} --config=/secrets/matrix-mas-secret-config.secret";
|
|
||||||
WorkingDirectory = "${pkgs.matrix-authentication-service}";
|
|
||||||
User = "matrix-synapse";
|
|
||||||
Group = "matrix-synapse";
|
|
||||||
};
|
|
||||||
|
|
||||||
wantedBy = [
|
|
||||||
"multi-user.target"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
services.matrix-synapse = {
|
services.matrix-synapse = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
listeners = [
|
listeners = [{
|
||||||
{
|
|
||||||
port = 8008;
|
port = 8008;
|
||||||
bind_addresses = [
|
bind_addresses = [
|
||||||
"::1"
|
"::1"
|
||||||
|
|
@ -23,20 +22,7 @@
|
||||||
names = [ "federation" ];
|
names = [ "federation" ];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
|
||||||
{
|
|
||||||
port = 9000;
|
|
||||||
type = "http";
|
|
||||||
tls = false;
|
|
||||||
bind_addresses = [
|
|
||||||
"0.0.0.0"
|
|
||||||
];
|
|
||||||
resources = [{
|
|
||||||
names = [ "metrics" ];
|
|
||||||
compress = false;
|
|
||||||
}];
|
}];
|
||||||
}
|
|
||||||
];
|
|
||||||
server_name = "nekover.se";
|
server_name = "nekover.se";
|
||||||
public_baseurl = "https://matrix.nekover.se";
|
public_baseurl = "https://matrix.nekover.se";
|
||||||
database = {
|
database = {
|
||||||
|
|
@ -54,42 +40,19 @@
|
||||||
signing_key_path = "/secrets/matrix-homeserver-signing-key.secret";
|
signing_key_path = "/secrets/matrix-homeserver-signing-key.secret";
|
||||||
admin_contact = "mailto:admin@nekover.se";
|
admin_contact = "mailto:admin@nekover.se";
|
||||||
web_client_location = "https://element.nekover.se";
|
web_client_location = "https://element.nekover.se";
|
||||||
enable_metrics = true;
|
|
||||||
turn_uris = [
|
turn_uris = [
|
||||||
"turns:turn.nekover.se?transport=udp"
|
"turns:turn.nekover.se?transport=udp"
|
||||||
"turns:turn.nekover.se?transport=tcp"
|
"turns:turn.nekover.se?transport=tcp"
|
||||||
];
|
];
|
||||||
turn_user_lifetime = 86400000;
|
turn_user_lifetime = 86400000;
|
||||||
turn_allow_guests = true;
|
turn_allow_guests = true;
|
||||||
experimental_features = {
|
|
||||||
# MSC3266: Room summary API. Used for knocking over federation
|
|
||||||
msc3266_enabled = true;
|
|
||||||
# MSC4222 needed for syncv2 state_after. This allow clients to
|
|
||||||
# correctly track the state of the room.
|
|
||||||
msc4222_enabled = true;
|
|
||||||
};
|
|
||||||
# The maximum allowed duration by which sent events can be delayed, as
|
|
||||||
# per MSC4140.
|
|
||||||
max_event_delay_duration = "24h";
|
|
||||||
rc_message = {
|
|
||||||
# This needs to match at least e2ee key sharing frequency plus a bit of headroom
|
|
||||||
# Note key sharing events are bursty
|
|
||||||
per_second = 0.5;
|
|
||||||
burst_count = 30;
|
|
||||||
};
|
|
||||||
rc_delayed_event_mgmt = {
|
|
||||||
# This needs to match at least the heart-beat frequency plus a bit of headroom
|
|
||||||
# Currently the heart-beat is every 5 seconds which translates into a rate of 0.2s
|
|
||||||
per_second = 1;
|
|
||||||
burst_count = 20;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
extras = [ "oidc" ];
|
extras = [ "oidc" ];
|
||||||
extraConfigFiles = [
|
extraConfigFiles = [
|
||||||
"/secrets/matrix-registration-shared-secret.secret"
|
"/secrets/matrix-registration-shared-secret.secret"
|
||||||
"/secrets/matrix-turn-shared-secret.secret"
|
"/secrets/matrix-turn-shared-secret.secret"
|
||||||
"/secrets/matrix-email-smtp-pass.secret"
|
"/secrets/matrix-email-smtp-pass.secret"
|
||||||
"/secrets/matrix-homeserver-mas-config.secret"
|
"/secrets/matrix-keycloak-client-secret.secret"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
{
|
{
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
virtualHosts = {
|
virtualHosts."matrix.nekover.se" = {
|
||||||
"matrix.nekover.se" = {
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
listen = [
|
listen = [
|
||||||
|
|
@ -11,44 +10,20 @@
|
||||||
addr = "0.0.0.0";
|
addr = "0.0.0.0";
|
||||||
port = 80;
|
port = 80;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 8443;
|
|
||||||
ssl = true;
|
|
||||||
proxyProtocol = true;
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
addr = "0.0.0.0";
|
addr = "0.0.0.0";
|
||||||
port = 8448;
|
port = 8448;
|
||||||
ssl = true;
|
ssl = true;
|
||||||
proxyProtocol = true;
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
locations = {
|
locations = {
|
||||||
"~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync)" = {
|
"~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync)" = {
|
||||||
proxyPass = "http://localhost:8009";
|
proxyPass = "http://127.0.0.1:8009";
|
||||||
priority = 998;
|
|
||||||
};
|
|
||||||
"~ ^/_matrix/client/(.*)/(login|logout|refresh)" = {
|
|
||||||
proxyPass = "http://localhost:8080";
|
|
||||||
priority = 999;
|
priority = 999;
|
||||||
};
|
};
|
||||||
"~ ^(/_matrix|/_synapse/client)" = {
|
"~ ^(/_matrix|/_synapse/client)" = {
|
||||||
proxyPass = "http://localhost:8008";
|
|
||||||
extraConfig = ''
|
|
||||||
# Nginx by default only allows file uploads up to 1M in size
|
|
||||||
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
|
|
||||||
client_max_body_size ${config.services.matrix-synapse.settings.max_upload_size};
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
"~ ^/_synapse/admin" = {
|
|
||||||
# Only proxy to the local host on IPv4, because localhost doesn't seem to work
|
|
||||||
# even if matrix-synapse is listening on ::1 as well.
|
|
||||||
proxyPass = "http://127.0.0.1:8008";
|
proxyPass = "http://127.0.0.1:8008";
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
# Restrict access to admin API.
|
|
||||||
allow 172.21.87.0/24; # management VPN
|
|
||||||
deny all;
|
|
||||||
# Nginx by default only allows file uploads up to 1M in size
|
# Nginx by default only allows file uploads up to 1M in size
|
||||||
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
|
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
|
||||||
client_max_body_size ${config.services.matrix-synapse.settings.max_upload_size};
|
client_max_body_size ${config.services.matrix-synapse.settings.max_upload_size};
|
||||||
|
|
@ -56,73 +31,11 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
|
set_real_ip_from 10.202.41.100;
|
||||||
real_ip_header proxy_protocol;
|
real_ip_header proxy_protocol;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
"mas.nekover.se" = {
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
listen = [
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 80;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 8443;
|
|
||||||
ssl = true;
|
|
||||||
proxyProtocol = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
locations = {
|
|
||||||
"/" = {
|
|
||||||
proxyPass = "http://localhost:8080";
|
|
||||||
};
|
|
||||||
"~ ^/api/admin" = {
|
|
||||||
proxyPass = "http://localhost:8083";
|
|
||||||
extraConfig = ''
|
|
||||||
# Restrict access to admin API.
|
|
||||||
allow 172.21.87.0/24; # management VPN
|
|
||||||
deny all;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
extraConfig = ''
|
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
"matrix-rtc.nekover.se" = {
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
listen = [
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 80;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 8443;
|
|
||||||
ssl = true;
|
|
||||||
proxyProtocol = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
locations."^~ /livekit/jwt/" = {
|
|
||||||
proxyPass = "http://localhost:8082/";
|
|
||||||
};
|
|
||||||
locations."^~ /livekit/sfu/" = {
|
|
||||||
proxyPass = "http://localhost:7880/";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
};
|
|
||||||
extraConfig = ''
|
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,6 @@
|
||||||
TEMPLATE template0
|
TEMPLATE template0
|
||||||
LC_COLLATE = "C"
|
LC_COLLATE = "C"
|
||||||
LC_CTYPE = "C";
|
LC_CTYPE = "C";
|
||||||
CREATE ROLE "mas_user" WITH LOGIN PASSWORD 'mas';
|
|
||||||
CREATE DATABASE "mas" WITH OWNER "mas_user"
|
|
||||||
TEMPLATE template0
|
|
||||||
LC_COLLATE = "C"
|
|
||||||
LC_CTYPE = "C";
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,29 +33,13 @@
|
||||||
permissions = "0640";
|
permissions = "0640";
|
||||||
uploadAt = "pre-activation";
|
uploadAt = "pre-activation";
|
||||||
};
|
};
|
||||||
"matrix-homeserver-mas-config.secret" = {
|
"matrix-keycloak-client-secret.secret" = {
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "matrix/homeserver-mas-config" ];
|
keyCommand = keyCommandEnv ++ [ "pass" "matrix/keycloak-client-secret" ];
|
||||||
destDir = "/secrets";
|
destDir = "/secrets";
|
||||||
user = "matrix-synapse";
|
user = "matrix-synapse";
|
||||||
group = "matrix-synapse";
|
group = "matrix-synapse";
|
||||||
permissions = "0640";
|
permissions = "0640";
|
||||||
uploadAt = "pre-activation";
|
uploadAt = "pre-activation";
|
||||||
};
|
};
|
||||||
"matrix-mas-secret-config.secret" = {
|
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "matrix/mas-secret-config" ];
|
|
||||||
destDir = "/secrets";
|
|
||||||
user = "matrix-synapse";
|
|
||||||
group = "matrix-synapse";
|
|
||||||
permissions = "0640";
|
|
||||||
uploadAt = "pre-activation";
|
|
||||||
};
|
|
||||||
"matrix-livekit-secret-key.secret" = {
|
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "matrix/livekit-secret-key" ];
|
|
||||||
destDir = "/secrets";
|
|
||||||
user = "root";
|
|
||||||
group = "root";
|
|
||||||
permissions = "0640";
|
|
||||||
uploadAt = "pre-activation";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
{ config, ... }:
|
|
||||||
{
|
|
||||||
services.grafana = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
server = {
|
|
||||||
domain = "mesh.nekover.se";
|
|
||||||
root_url = "https://${config.services.grafana.settings.server.domain}";
|
|
||||||
};
|
|
||||||
security = {
|
|
||||||
cookie_secure = true;
|
|
||||||
cookie_samesite = "strict";
|
|
||||||
admin_user = "admin";
|
|
||||||
admin_password = "$__file{/secrets/metrics-nekomesh-grafana-admin-password.secret}";
|
|
||||||
admin_email = "fi@nekover.se";
|
|
||||||
secret_key = "$__file{/secrets/metrics-nekomesh-grafana-secret-key.secret}";
|
|
||||||
};
|
|
||||||
smtp = {
|
|
||||||
enabled = true;
|
|
||||||
host = "mail.grzb.de:465";
|
|
||||||
user = "nekomesh@grzb.de";
|
|
||||||
password = "$__file{/secrets/mail-nekomesh-nekover-se.secret}";
|
|
||||||
from_address = "nyareply@nekover.se";
|
|
||||||
from_name = "Nekomesh";
|
|
||||||
startTLS_policy = "NoStartTLS";
|
|
||||||
};
|
|
||||||
"auth.generic_oauth" = {
|
|
||||||
enabled = true;
|
|
||||||
name = "Nekoverse ID";
|
|
||||||
allow_sign_up = true;
|
|
||||||
client_id = "nekomesh";
|
|
||||||
client_secret = "$__file{/secrets/metrics-nekomesh-grafana-keycloak-client-secret.secret}";
|
|
||||||
scopes = "openid email profile offline_access roles";
|
|
||||||
email_attribute_path = "email";
|
|
||||||
login_attribute_path = "preferred_username";
|
|
||||||
name_attribute_path = "preferred_username";
|
|
||||||
auth_url = "https://id.nekover.se/realms/nekoverse/protocol/openid-connect/auth";
|
|
||||||
token_url = "https://id.nekover.se/realms/nekoverse/protocol/openid-connect/token";
|
|
||||||
api_url = "https://id.nekover.se/realms/nekoverse/protocol/openid-connect/userinfo";
|
|
||||||
use_refresh_token = true;
|
|
||||||
allow_assign_grafana_admin = true;
|
|
||||||
role_attribute_strict = true;
|
|
||||||
role_attribute_path = "contains(resource_access.nekomesh.roles[*], 'grafanaadmin') && 'GrafanaAdmin' || contains(resource_access.nekomesh.roles[*], 'admin') && 'Admin' || contains(resource_access.nekomesh.roles[*], 'editor') && 'Editor' || 'Viewer'";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
provision.datasources.settings.datasources = [
|
|
||||||
{
|
|
||||||
name = "Prometheus";
|
|
||||||
type = "prometheus";
|
|
||||||
url = "http://localhost:${builtins.toString config.services.prometheus.port}";
|
|
||||||
isDefault = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
services.neo4j = {
|
|
||||||
enable = true;
|
|
||||||
https.enable = false;
|
|
||||||
bolt.tlsLevel = "DISABLED";
|
|
||||||
defaultListenAddress = "0.0.0.0";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
{ config, ... }:
|
|
||||||
{
|
|
||||||
services.nginx = {
|
|
||||||
enable = true;
|
|
||||||
virtualHosts = {
|
|
||||||
${config.services.grafana.settings.server.domain} = {
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
listen = [
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 80;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 8443;
|
|
||||||
ssl = true;
|
|
||||||
extraParameters = [ "proxy_protocol" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://${config.services.grafana.settings.server.http_addr}:${builtins.toString config.services.grafana.settings.server.http_port}";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
};
|
|
||||||
extraConfig = ''
|
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
services.prometheus = {
|
|
||||||
enable = true;
|
|
||||||
retentionTime = "2y";
|
|
||||||
scrapeConfigs = [
|
|
||||||
{
|
|
||||||
job_name = "meshcore_repeater_telemetry";
|
|
||||||
scrape_interval = "15m";
|
|
||||||
static_configs = [{
|
|
||||||
targets = [ "localhost:9091" ];
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
pushgateway = {
|
|
||||||
enable = true;
|
|
||||||
web.external-url = "metrics-nekomesh.vs.grzb.de:9091";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
{ keyCommandEnv, ... }:
|
|
||||||
{
|
|
||||||
deployment.keys = {
|
|
||||||
"metrics-nekomesh-grafana-admin-password.secret" = {
|
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "metrics-nekomesh/grafana/admin-password" ];
|
|
||||||
destDir = "/secrets";
|
|
||||||
user = "grafana";
|
|
||||||
group = "grafana";
|
|
||||||
permissions = "0640";
|
|
||||||
uploadAt = "pre-activation";
|
|
||||||
};
|
|
||||||
"metrics-nekomesh-grafana-keycloak-client-secret.secret" = {
|
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "metrics-nekomesh/grafana/keycloak-client-secret" ];
|
|
||||||
destDir = "/secrets";
|
|
||||||
user = "grafana";
|
|
||||||
group = "grafana";
|
|
||||||
permissions = "0640";
|
|
||||||
uploadAt = "pre-activation";
|
|
||||||
};
|
|
||||||
"metrics-nekomesh-grafana-secret-key.secret" = {
|
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "metrics-nekomesh/grafana/secret-key" ];
|
|
||||||
destDir = "/secrets";
|
|
||||||
user = "grafana";
|
|
||||||
group = "grafana";
|
|
||||||
permissions = "0640";
|
|
||||||
uploadAt = "pre-activation";
|
|
||||||
};
|
|
||||||
"mail-nekomesh-nekover-se.secret" = {
|
|
||||||
keyCommand = keyCommandEnv ++ [ "pass" "mail/nekomesh-nekover-se" ];
|
|
||||||
destDir = "/secrets";
|
|
||||||
user = "grafana";
|
|
||||||
group = "grafana";
|
|
||||||
permissions = "0640";
|
|
||||||
uploadAt = "pre-activation";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,5 @@
|
||||||
./grafana.nix
|
./grafana.nix
|
||||||
./prometheus.nix
|
./prometheus.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,7 @@
|
||||||
{ hosts, pkgs, ... }:
|
{ hosts, ... }:
|
||||||
let
|
|
||||||
# https://github.com/element-hq/synapse/tree/master/contrib/prometheus/
|
|
||||||
synapseRules = pkgs.fetchurl {
|
|
||||||
url = "https://raw.githubusercontent.com/element-hq/synapse/refs/heads/master/contrib/prometheus/synapse-v2.rules";
|
|
||||||
hash = "sha256-X6GHOUDIMUat7R/yIfrIdO8ehomYiwDBFe3TUQYXDWQ=";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
services.prometheus = {
|
services.prometheus = {
|
||||||
enable = true;
|
enable = true;
|
||||||
retentionTime = "90d";
|
|
||||||
ruleFiles = [ synapseRules ];
|
|
||||||
scrapeConfigs = [
|
scrapeConfigs = [
|
||||||
{
|
{
|
||||||
job_name = "node";
|
job_name = "node";
|
||||||
|
|
@ -23,14 +14,6 @@ in
|
||||||
};
|
};
|
||||||
}) (builtins.attrNames hosts);
|
}) (builtins.attrNames hosts);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
job_name = "synapse";
|
|
||||||
scrape_interval = "15s";
|
|
||||||
metrics_path = "/_synapse/metrics";
|
|
||||||
static_configs = [{
|
|
||||||
targets = [ "matrix.vs.grzb.de:9000" ];
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
33
config/hosts/navidrome/configuration.nix
Normal file
33
config/hosts/navidrome/configuration.nix
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
boot.loader.grub = {
|
||||||
|
enable = true;
|
||||||
|
device = "/dev/vda";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
hostName = "navidrome";
|
||||||
|
firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [ 80 443 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems = {
|
||||||
|
"/mnt/music" = {
|
||||||
|
device = "//10.202.40.5/music-ro";
|
||||||
|
fsType = "cifs";
|
||||||
|
options = [
|
||||||
|
"username=navidrome"
|
||||||
|
"credentials=/secrets/navidrome-samba-credentials.secret"
|
||||||
|
"iocharset=utf8"
|
||||||
|
"vers=3.1.1"
|
||||||
|
"uid=navidrome"
|
||||||
|
"gid=navidrome"
|
||||||
|
"_netdev"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.05";
|
||||||
|
}
|
||||||
7
config/hosts/navidrome/default.nix
Normal file
7
config/hosts/navidrome/default.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{ ... }: {
|
||||||
|
imports = [
|
||||||
|
./configuration.nix
|
||||||
|
./navidrome.nix
|
||||||
|
./nginx.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
9
config/hosts/navidrome/navidrome.nix
Normal file
9
config/hosts/navidrome/navidrome.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{ ... }: {
|
||||||
|
services.navidrome = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
Address = "unix:/run/navidrome/navidrome.socket";
|
||||||
|
MusicFolder = "/mnt/music";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
24
config/hosts/navidrome/nginx.nix
Normal file
24
config/hosts/navidrome/nginx.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{ ... }: {
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
user = "navidrome";
|
||||||
|
virtualHosts."navidrome.grzb.de" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 443;
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://unix:/run/navidrome/navidrome.socket";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
config/hosts/navidrome/secrets.nix
Normal file
13
config/hosts/navidrome/secrets.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys = {
|
||||||
|
"navidrome-samba-credentials.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "navidrome/samba-credentials" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "root";
|
||||||
|
group = "root";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -6,12 +6,12 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = "metrics-nekomesh";
|
hostName = "netbox";
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowedTCPPorts = [ 80 7474 7687 8443 9091 ];
|
allowedTCPPorts = [ 80 443 ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "25.11";
|
system.stateVersion = "23.05";
|
||||||
}
|
}
|
||||||
8
config/hosts/netbox/default.nix
Normal file
8
config/hosts/netbox/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./configuration.nix
|
||||||
|
./netbox.nix
|
||||||
|
./nginx.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
8
config/hosts/netbox/netbox.nix
Normal file
8
config/hosts/netbox/netbox.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.netbox = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.netbox;
|
||||||
|
secretKeyFile = "/secrets/netbox-secret-key.secret";
|
||||||
|
};
|
||||||
|
}
|
||||||
29
config/hosts/netbox/nginx.nix
Normal file
29
config/hosts/netbox/nginx.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
clientMaxBodySize = "25m";
|
||||||
|
user = "netbox";
|
||||||
|
virtualHosts."netbox.grzb.de" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 443;
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
locations."/static/" = {
|
||||||
|
alias = "${config.services.netbox.dataDir}/static/";
|
||||||
|
};
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${config.services.netbox.listenAddress}:${builtins.toString config.services.netbox.port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
11
config/hosts/netbox/secrets.nix
Normal file
11
config/hosts/netbox/secrets.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{ keyCommandEnv, ... }:
|
||||||
|
{
|
||||||
|
deployment.keys."netbox-secret-key.secret" = {
|
||||||
|
keyCommand = keyCommandEnv ++ [ "pass" "netbox/secret-key" ];
|
||||||
|
destDir = "/secrets";
|
||||||
|
user = "netbox";
|
||||||
|
group = "netbox";
|
||||||
|
permissions = "0640";
|
||||||
|
uploadAt = "pre-activation";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,5 @@
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./nextcloud.nix
|
./nextcloud.nix
|
||||||
./sops.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
{
|
{
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.nextcloud32;
|
package = pkgs.nextcloud29;
|
||||||
hostName = "cloud.nekover.se";
|
hostName = "cloud.nekover.se";
|
||||||
https = true;
|
https = true;
|
||||||
config = {
|
config = {
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
mail_from_address = "cloud";
|
mail_from_address = "cloud";
|
||||||
mail_domain = "nekover.se";
|
mail_domain = "nekover.se";
|
||||||
mail_smtpauthtype = "LOGIN";
|
mail_smtpauthtype = "LOGIN";
|
||||||
mail_smtpauth = true;
|
mail_smtpauth = 1;
|
||||||
mail_smtphost = "mail-1.grzb.de";
|
mail_smtphost = "mail-1.grzb.de";
|
||||||
mail_smtpport = 465;
|
mail_smtpport = 465;
|
||||||
mail_smtpname = "cloud@nekover.se";
|
mail_smtpname = "cloud@nekover.se";
|
||||||
|
|
@ -44,8 +44,7 @@
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
||||||
|
|
||||||
set_real_ip_from 10.202.41.100; # IPv4 from web-public-2
|
set_real_ip_from 10.202.41.100;
|
||||||
set_real_ip_from 10.203.10.3; # IPv6 from valkyrie
|
|
||||||
real_ip_header proxy_protocol;
|
real_ip_header proxy_protocol;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sops = {
|
|
||||||
defaultSopsFile = ./secrets.yaml;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
17
config/hosts/nitter/configuration.nix
Normal file
17
config/hosts/nitter/configuration.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
boot.loader.grub = {
|
||||||
|
enable = true;
|
||||||
|
device = "/dev/vda";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
hostName = "nitter";
|
||||||
|
firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [ 8443 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.05";
|
||||||
|
}
|
||||||
8
config/hosts/nitter/default.nix
Normal file
8
config/hosts/nitter/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./configuration.nix
|
||||||
|
./nginx.nix
|
||||||
|
./nitter.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
23
config/hosts/nitter/nginx.nix
Normal file
23
config/hosts/nitter/nginx.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts."birdsite.nekover.se" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/robots.txt" = {
|
||||||
|
return = "200 \"User-agent: *\\nDisallow: /\\n\"";
|
||||||
|
};
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${config.services.nitter.server.address}:${builtins.toString config.services.nitter.server.port}";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
extraConfig = ''
|
||||||
|
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
|
||||||
|
|
||||||
|
set_real_ip_from 10.202.41.100;
|
||||||
|
real_ip_header proxy_protocol;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
21
config/hosts/nitter/nitter.nix
Normal file
21
config/hosts/nitter/nitter.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
services.nitter = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
server = {
|
||||||
|
title = "Birdsite";
|
||||||
|
https = true;
|
||||||
|
address = "127.0.0.1";
|
||||||
|
port = 8080;
|
||||||
|
hostname = "birdsite.nekover.se";
|
||||||
|
};
|
||||||
|
|
||||||
|
preferences = {
|
||||||
|
theme = "Mastodon";
|
||||||
|
replaceTwitter = "birdsite.nekover.se";
|
||||||
|
infiniteScroll = true;
|
||||||
|
hlsPlayback = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
17
config/hosts/paperless/configuration.nix
Normal file
17
config/hosts/paperless/configuration.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
boot.loader.grub = {
|
||||||
|
enable = true;
|
||||||
|
device = "/dev/vda";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
hostName = "paperless";
|
||||||
|
firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [ 80 443 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.05";
|
||||||
|
}
|
||||||
9
config/hosts/paperless/default.nix
Normal file
9
config/hosts/paperless/default.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./configuration.nix
|
||||||
|
./hardware-configuration.nix
|
||||||
|
./nginx.nix
|
||||||
|
./paperless.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
30
config/hosts/paperless/hardware-configuration.nix
Normal file
30
config/hosts/paperless/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
fileSystems = {
|
||||||
|
"/mnt/data" = {
|
||||||
|
device = "/dev/disk/by-label/data";
|
||||||
|
fsType = "ext4";
|
||||||
|
autoFormat = true;
|
||||||
|
autoResize = true;
|
||||||
|
};
|
||||||
|
"/mnt/paperless-consume" = {
|
||||||
|
device = "//10.201.40.10/paperless-consume";
|
||||||
|
fsType = "cifs";
|
||||||
|
options = [
|
||||||
|
"username=paperless"
|
||||||
|
"credentials=/secrets/paperless-samba-credentials.secret"
|
||||||
|
"iocharset=utf8"
|
||||||
|
"vers=3.1.1"
|
||||||
|
"uid=paperless"
|
||||||
|
"gid=paperless"
|
||||||
|
"_netdev"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"/var/lib/paperless" = {
|
||||||
|
depends = [ "/mnt/data" ];
|
||||||
|
device = "/mnt/data/paperless";
|
||||||
|
fsType = "none";
|
||||||
|
options = [ "bind" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
31
config/hosts/paperless/nginx.nix
Normal file
31
config/hosts/paperless/nginx.nix
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts."paperless.grzb.de" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 443;
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${config.services.paperless.address}:${builtins.toString config.services.paperless.port}";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
extraConfig = ''
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
extraConfig = ''
|
||||||
|
client_max_body_size 100M;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue