feat: mail server
This commit is contained in:
parent
396a4d603d
commit
1e77f204d0
13 changed files with 320 additions and 57 deletions
|
|
@ -31,3 +31,22 @@ vim.g.mkdp_combine_preview = 1
|
||||||
vim.g.mkdp_echo_preview_url = 1
|
vim.g.mkdp_echo_preview_url = 1
|
||||||
vim.g.mkdp_open_to_the_world = 1
|
vim.g.mkdp_open_to_the_world = 1
|
||||||
vim.g.mkdp_port = "20088"
|
vim.g.mkdp_port = "20088"
|
||||||
|
|
||||||
|
-- Use osc52 as clipboard provider
|
||||||
|
local function paste()
|
||||||
|
return { vim.fn.split(vim.fn.getreg(""), "\n"), vim.fn.getregtype("") }
|
||||||
|
end
|
||||||
|
vim.g.clipboard = {
|
||||||
|
name = "OSC 52",
|
||||||
|
copy = {
|
||||||
|
["+"] = require("vim.ui.clipboard.osc52").copy("+"),
|
||||||
|
["*"] = require("vim.ui.clipboard.osc52").copy("*"),
|
||||||
|
},
|
||||||
|
paste = {
|
||||||
|
["+"] = paste,
|
||||||
|
["*"] = paste,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
-- To ALWAYS use the clipboard for ALL operations
|
||||||
|
-- (instead of interacting with the "+" and/or "*" registers explicitly):
|
||||||
|
vim.opt.clipboard = "unnamedplus"
|
||||||
|
|
|
||||||
|
|
@ -33,5 +33,7 @@
|
||||||
GTK_CSD = "0";
|
GTK_CSD = "0";
|
||||||
GTK_USE_PORTAL = "1";
|
GTK_USE_PORTAL = "1";
|
||||||
GTK_IM_MODULE = "";
|
GTK_IM_MODULE = "";
|
||||||
|
|
||||||
|
MAIL = "~/Mailbox";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,18 @@ let
|
||||||
|
|
||||||
tmux switch-client -t $selected_name
|
tmux switch-client -t $selected_name
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
ryank = pkgs.writeShellScriptBin "ryank" ''
|
||||||
|
# copy via OSC 52
|
||||||
|
buf=$( cat "$@" )
|
||||||
|
len=$( printf %s "$buf" | wc -c ) max=74994
|
||||||
|
test $len -gt $max && echo "$0: input is $(( len - max )) bytes too long" >&2
|
||||||
|
printf "\033]52;c;$( printf %s "$buf" | head -c $max | base64 | tr -d '\r\n' )\a"
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
home.packages = [
|
home.packages = [
|
||||||
tmuxSessionizer
|
tmuxSessionizer
|
||||||
|
ryank
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@
|
||||||
dataBackupPath = "/mnt/backup_dn";
|
dataBackupPath = "/mnt/backup_dn";
|
||||||
dbBackupPath = "/mnt/backup_dn";
|
dbBackupPath = "/mnt/backup_dn";
|
||||||
})
|
})
|
||||||
|
(import ../../modules/vaultwarden.nix {
|
||||||
|
domain = "https://bitwarden.net.dn";
|
||||||
|
})
|
||||||
|
(import ../../modules/openldap.nix { })
|
||||||
];
|
];
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
|
pkgs,
|
||||||
settings,
|
settings,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
@ -16,7 +17,10 @@ let
|
||||||
# fqdn = "dn-server.daccc.info";
|
# fqdn = "dn-server.daccc.info";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
networking.firewall.allowedTCPPorts = [ 25 ];
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
25
|
||||||
|
587
|
||||||
|
];
|
||||||
|
|
||||||
services.postfix = {
|
services.postfix = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -29,9 +33,17 @@ in
|
||||||
fqdn
|
fqdn
|
||||||
];
|
];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
home_mailbox = "Mailbox";
|
||||||
|
};
|
||||||
|
|
||||||
postmasterAlias = "root";
|
postmasterAlias = "root";
|
||||||
rootAlias = settings.personal.username;
|
rootAlias = settings.personal.username;
|
||||||
|
|
||||||
|
config = {
|
||||||
|
alias_maps = [ "ldap:${config.sops.secrets."postfix/openldap".path}" ];
|
||||||
|
};
|
||||||
|
|
||||||
extraAliases = ''
|
extraAliases = ''
|
||||||
mailer-daemon: postmaster
|
mailer-daemon: postmaster
|
||||||
nobody: root
|
nobody: root
|
||||||
|
|
@ -44,6 +56,7 @@ in
|
||||||
abuse: root
|
abuse: root
|
||||||
noc: root
|
noc: root
|
||||||
security: root
|
security: root
|
||||||
|
vaultwarden: root
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,76 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
acmeWebRoot = "/var/www/${config.services.nextcloud.hostName}/html/";
|
mkProxyHost = (
|
||||||
|
{
|
||||||
|
domain,
|
||||||
|
proxyPass,
|
||||||
|
ssl ? false,
|
||||||
|
}:
|
||||||
|
(
|
||||||
|
if ssl then
|
||||||
|
{
|
||||||
|
forceSSL = true;
|
||||||
|
sslCertificate = "/etc/letsencrypt/live/${domain}/fullchain.pem";
|
||||||
|
sslCertificateKey = "/etc/letsencrypt/live/${domain}/privkey.pem";
|
||||||
|
|
||||||
certScript = pkgs.writeShellScriptBin "certbot-nextcloud" ''
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 443;
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
)
|
||||||
|
// {
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = proxyPass;
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_set_header 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-Proto $scheme;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
locations."^~ /.well-known/acme-challenge/" = {
|
||||||
|
root = "/var/www/${domain}/html";
|
||||||
|
extraConfig = ''
|
||||||
|
default_type "text/plain";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = ''
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384';
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
certScript = pkgs.writeShellScriptBin "genCert" ''
|
||||||
|
acmeWebRoot="/var/www/$1/html/";
|
||||||
|
if [ ! -d "$acmeWebRoot" ]; then
|
||||||
|
mkdir -p "$acmeWebRoot"
|
||||||
|
fi
|
||||||
|
|
||||||
|
REQUESTS_CA_BUNDLE=${../../../system/extra/ca.crt} \
|
||||||
${pkgs.certbot}/bin/certbot certonly --webroot \
|
${pkgs.certbot}/bin/certbot certonly --webroot \
|
||||||
--webroot-path ${acmeWebRoot} -v \
|
--webroot-path $acmeWebRoot -v \
|
||||||
-d ${config.services.nextcloud.hostName} \
|
-d "$1" \
|
||||||
--server https://ca.net.dn:8443/acme/acme/directory \
|
--server https://ca.net.dn:8443/acme/acme/directory \
|
||||||
-m admin@mail.net.dn
|
-m admin@mail.net.dn
|
||||||
|
|
||||||
|
|
@ -21,17 +81,24 @@ let
|
||||||
hostname = "pre-nextcloud.net.dn";
|
hostname = "pre-nextcloud.net.dn";
|
||||||
ip = "10.0.0.130";
|
ip = "10.0.0.130";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vaultwarden = {
|
||||||
|
domain = "bitwarden.net.dn";
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
environment.systemPackages = [
|
||||||
|
certScript
|
||||||
|
];
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableReload = true;
|
enableReload = true;
|
||||||
|
|
||||||
virtualHosts = {
|
virtualHosts = {
|
||||||
# Nextcloud - Server
|
# Nextcloud - Server
|
||||||
|
|
||||||
${config.services.nextcloud.hostName} = {
|
${config.services.nextcloud.hostName} = {
|
||||||
listen = lib.mkForce [
|
listen = [
|
||||||
{
|
{
|
||||||
addr = "0.0.0.0";
|
addr = "0.0.0.0";
|
||||||
port = 443;
|
port = 443;
|
||||||
|
|
@ -61,46 +128,16 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
${pre7780.hostname} = {
|
${pre7780.hostname} = mkProxyHost {
|
||||||
listen = [
|
domain = pre7780.hostname;
|
||||||
{
|
proxyPass = "http://${pre7780.ip}";
|
||||||
addr = "0.0.0.0";
|
ssl = true;
|
||||||
port = 443;
|
};
|
||||||
ssl = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = 80;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://${pre7780.ip}/";
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_set_header 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-Proto $scheme;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
locations."^~ /.well-known/acme-challenge/" = {
|
|
||||||
root = "/var/www/${pre7780.hostname}/html";
|
|
||||||
extraConfig = ''
|
|
||||||
default_type "text/plain";
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
forceSSL = true;
|
|
||||||
sslCertificate = "/etc/letsencrypt/live/${pre7780.hostname}/fullchain.pem";
|
|
||||||
sslCertificateKey = "/etc/letsencrypt/live/${pre7780.hostname}/privkey.pem";
|
|
||||||
|
|
||||||
extraConfig = ''
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384';
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
'';
|
|
||||||
|
|
||||||
|
${vaultwarden.domain} = mkProxyHost {
|
||||||
|
domain = vaultwarden.domain;
|
||||||
|
proxyPass = "http://127.0.0.1:${builtins.toString config.services.vaultwarden.config.ROCKET_PORT}";
|
||||||
|
ssl = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,13 @@ nextcloud:
|
||||||
adminPassword: ENC[AES256_GCM,data:O2rK18+riVrvloqqLsMUXw==,iv:OosiF0g4l1mrgndbwUOvO2YUqxWVk1hvAZY0rHU9GPE=,tag:yh1ccDmthARLND0NwpLTCA==,type:str]
|
adminPassword: ENC[AES256_GCM,data:O2rK18+riVrvloqqLsMUXw==,iv:OosiF0g4l1mrgndbwUOvO2YUqxWVk1hvAZY0rHU9GPE=,tag:yh1ccDmthARLND0NwpLTCA==,type:str]
|
||||||
step_ca:
|
step_ca:
|
||||||
password: ENC[AES256_GCM,data:3EWxpk/ktZHJreqnR9ln5pfdPjgigoCC4lyoRWugHas=,iv:q9cWW8xTxYQnRYohBxnPIsbVSpvkZYVpYLRVeZgmsRM=,tag:UHZagnLvorZUrPq43YU+Gw==,type:str]
|
password: ENC[AES256_GCM,data:3EWxpk/ktZHJreqnR9ln5pfdPjgigoCC4lyoRWugHas=,iv:q9cWW8xTxYQnRYohBxnPIsbVSpvkZYVpYLRVeZgmsRM=,tag:UHZagnLvorZUrPq43YU+Gw==,type:str]
|
||||||
|
vaultwarden: ENC[AES256_GCM,data:PSKtHBIxw0/z/rmtF83Yg3btHksbVVyWZ80nP0wl4zAHRpFXypvpchZu9/edX7RgREd+9okm21WyjNWRUDoGVTOJYOCFHZCvOUx4KzIL2c/i7jUjXwtvAEmikhL1qlunVrCPhDu0knQ5nvsqpgWyxgcZl52yxuskMSIRAOsMpCRePVwJerWW5tuQ5zteYeOR0GHR8Q0iwBm98YGlCbKvz/37jAjMQVxY5W9DE1Tu1XVyEPBeAVvEwZknFNIZg1ukB+kW9Z/sBwLEVbAGsiBSGjonP6KEsgKmtaIkbBPzpfA3CQ==,iv:X8x3ooFDkFIT2OuHICcP2J1zX8T6xZW8j71ZuaByx6Q=,tag:mfnDFf9riivZ3EBup1l6lw==,type:str]
|
||||||
|
openldap:
|
||||||
|
adminPassword: ENC[AES256_GCM,data:dSaynM6RBrhZLOwcN2djaA==,iv:t2xJuRO2irEFgcnNcZS25qCfXiZXHaoqcCZYcR041aY=,tag:K5DiJRp+AumtKafAOR49/w==,type:str]
|
||||||
|
postfix:
|
||||||
|
openldap: ENC[AES256_GCM,data:8woTLrSJ5qqZU7jizOIK9VGlaPaBuyhq6FOs6LwiE9WHYJzWCAw3D+449SmCVeEE2t+EZWmfRPaOQBceSeIfUY6WZ5vso1E29CWPq8Tk7AuHT2i/K82EhpapXst61IAgSa/y39MchA7LqwaiTzL3A2CJVM1k5Ay5iHUUDfXvLbUsVmn1NlNfOv2QPPd5g+2yR2oGGx5HTbTPQNfoiU77KtvtFmlrubAs413I3DGdhM4uiOS+FI9WgZ4Ia22BucaOLHp2odfWnEMbP+ZIyJFdu3CBcs1lbTnLLVI=,iv:RvPm2+WsTIPFWLlYzv/OyKKDy/fWhtEfut98mBoM/1A=,tag:wkkWK88D0jKfaudN+KpN0Q==,type:str]
|
||||||
|
dovecot:
|
||||||
|
openldap: ENC[AES256_GCM,data:G7jdoSqL2SYDv2alh7q65BaA8Ap898azUPf2KKWd5wbr9pRVsRhFxQxHdZDuTOHDhWcfaa+eqMgc5k9gGLBYIO9EWVyEZ01/QfG4GIHSDjubzZxCElwhJrtsFn1A+Ihv7T1IIGKBCdmQGhUwfBMtwYlIuj8PYZaty4+c/dxIOCfDr5HyM1C6qQ4RCJTDEh6B+Hpx8NlFO0+fRFC9+9tQYX0rjI7JZRSfbg7F23nEdkBATr/xlwQXj8dvXYMLZhUKaswFnRs5TrG97AVQ9t3rMguRHutCAqEROhml2lJvV3Vxb/yMmTrom8qSrbkuw00YfdlDCmUo5/E4Vu9DYL0kv0EnASyQ4vQbmVXz0clYEzEXBLWZIEu4QHGJ7jQWgsKFv+WSTvuunVQyNuij3SFWZLR/zdfJELxU,iv:bsGMMdDo1Mj4GxRbWuRmbH/WrLt25jK3we8JDYQRsLw=,tag:EugvDijjQnYcms70nZq5FQ==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
|
|
@ -19,8 +26,8 @@ sops:
|
||||||
Qm0wbmNGZDZwZlNTOVl0WVh5RXNxK2cK1Fwbgl5kKAFyrIIhBP+X4ZKFS4Xl39QY
|
Qm0wbmNGZDZwZlNTOVl0WVh5RXNxK2cK1Fwbgl5kKAFyrIIhBP+X4ZKFS4Xl39QY
|
||||||
11qkglNgro/JBFJ/W7Hj5wtEd8QToiJM1RW0lQaI25sneQ2v6L5pDA==
|
11qkglNgro/JBFJ/W7Hj5wtEd8QToiJM1RW0lQaI25sneQ2v6L5pDA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-04-22T06:01:27Z"
|
lastmodified: "2025-05-04T13:11:13Z"
|
||||||
mac: ENC[AES256_GCM,data:HQHGQRuRR93Lwny8Bbv3Po2xSNvKgrLJhXC7txwwwO0Qh4Q3HjngpJqTQZg8KXe6PyNj8iPSnqW3Bt1jjOv9vjPPQVhRiUFy5pMBd/aK7mkBhTbvN4CMj5y1egU6TBMceRvlU5rhtPSsiIzq1egA/YOsfyeAXkLBghDRZmabq8s=,iv:IAvO0Kewx9D7NxWQ5K9heQtdksK7xfvl0eQCU1n0bmU=,tag:KPNbBeqXTeei+CXyL1NaOw==,type:str]
|
mac: ENC[AES256_GCM,data:+V5vP4XbeXQP49gyisV4uQJjUybtK792DaFEWBHzLlKn2HiRj+qqSVR5XQrQMQQ5mKMhzsZXGq7QjjXtzKqgLCz5snItU63HzxQ6OxarNeg5pctk7i8ueNST4JpMxZODKGJncz2Ysq8OGrjZ6Nf4QVjO0XhFxZP6MbZxZL7wbuY=,iv:7jKt3uAY/ks8m/uzpos6XvldkpQjkgCHcLn+oRiY3mk=,tag:d6V+waMu4m2wi/H/J3bMXg==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.9.4
|
version: 3.9.4
|
||||||
|
|
|
||||||
|
|
@ -382,10 +382,11 @@ in
|
||||||
IN NS dns.${origin}
|
IN NS dns.${origin}
|
||||||
@ IN A ${serverIP}
|
@ IN A ${serverIP}
|
||||||
IN AAAA fe80::3319:e2bb:fc15:c9df
|
IN AAAA fe80::3319:e2bb:fc15:c9df
|
||||||
IN MX 10 mail.${origin}
|
@ IN MX 10 mail.${origin}
|
||||||
IN TXT "v=spf1 mx"
|
IN TXT "v=spf1 mx"
|
||||||
dns IN A ${serverIP}
|
dns IN A ${serverIP}
|
||||||
nextcloud IN A ${serverIP}
|
nextcloud IN A ${serverIP}
|
||||||
|
bitwarden IN A ${serverIP}
|
||||||
pre-nextcloud IN A ${serverIP}
|
pre-nextcloud IN A ${serverIP}
|
||||||
ca IN A ${serverIP}
|
ca IN A ${serverIP}
|
||||||
${hostname} IN A ${serverIP}
|
${hostname} IN A ${serverIP}
|
||||||
|
|
@ -406,7 +407,6 @@ in
|
||||||
file =
|
file =
|
||||||
let
|
let
|
||||||
serverIP = getSubAddress personal.ip;
|
serverIP = getSubAddress personal.ip;
|
||||||
mailIP = getSubAddress personal.ip;
|
|
||||||
hostname = config.networking.hostName;
|
hostname = config.networking.hostName;
|
||||||
in
|
in
|
||||||
pkgs.writeText "${getReverseFilename personal.ip}" ''
|
pkgs.writeText "${getReverseFilename personal.ip}" ''
|
||||||
|
|
@ -420,11 +420,12 @@ in
|
||||||
IN NS dns.${personal.domain}.
|
IN NS dns.${personal.domain}.
|
||||||
|
|
||||||
${serverIP} IN PTR dns.${personal.domain}.
|
${serverIP} IN PTR dns.${personal.domain}.
|
||||||
|
${serverIP} IN PTR mail.${personal.domain}.
|
||||||
${serverIP} IN PTR ${hostname}.${personal.domain}.
|
${serverIP} IN PTR ${hostname}.${personal.domain}.
|
||||||
${serverIP} IN PTR nextcloud.${personal.domain}.
|
${serverIP} IN PTR nextcloud.${personal.domain}.
|
||||||
|
${serverIP} IN PTR bitwarden.${personal.domain}.
|
||||||
${serverIP} IN PTR pre-nextcloud.${personal.domain}.
|
${serverIP} IN PTR pre-nextcloud.${personal.domain}.
|
||||||
${serverIP} IN PTR ca.${personal.domain}.
|
${serverIP} IN PTR ca.${personal.domain}.
|
||||||
${mailIP} IN PTR mail.${personal.domain}.
|
|
||||||
${dnsReversedRecords}
|
${dnsReversedRecords}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
|
{ config, ... }:
|
||||||
{
|
{
|
||||||
sops = {
|
sops = {
|
||||||
secrets = {
|
secrets = {
|
||||||
"wireguard/privateKey" = { };
|
"wireguard/privateKey" = { };
|
||||||
"nextcloud/adminPassword" = { };
|
"nextcloud/adminPassword" = { };
|
||||||
"step_ca/password" = { };
|
"step_ca/password" = { };
|
||||||
|
vaultwarden = { };
|
||||||
|
"postfix/openldap" = { };
|
||||||
|
"openldap/adminPassword" = {
|
||||||
|
owner = config.users.users.openldap.name;
|
||||||
|
group = config.users.users.openldap.group;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,14 @@
|
||||||
ExecStart = ''${pkgs.certbot}/bin/certbot renew'';
|
ExecStart = ''${pkgs.certbot}/bin/certbot renew'';
|
||||||
ExecStartPost = "${pkgs.busybox}/bin/chown nginx:nginx -R /etc/letsencrypt";
|
ExecStartPost = "${pkgs.busybox}/bin/chown nginx:nginx -R /etc/letsencrypt";
|
||||||
};
|
};
|
||||||
unitConfig = {
|
|
||||||
OnSuccess = "nginx-reload-after-certbot.service";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."nginx-reload-after-certbot" = {
|
systemd.services."nginx-reload-after-certbot" = {
|
||||||
|
after = [ "certbot-renew.service" ];
|
||||||
|
requires = [ "certbot-renew.service" ];
|
||||||
|
wantedBy = [ "certbot-renew.service" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
User = "nginx";
|
User = "nginx";
|
||||||
# This config file path refers to "services.nginx.enableReload"
|
# This config file path refers to "services.nginx.enableReload"
|
||||||
ExecStart = ''${pkgs.nginx}/bin/nginx -s reload -c /etc/nginx/nginx.conf'';
|
ExecStart = ''${pkgs.nginx}/bin/nginx -s reload -c /etc/nginx/nginx.conf'';
|
||||||
|
|
|
||||||
129
system/modules/openldap.nix
Normal file
129
system/modules/openldap.nix
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
{
|
||||||
|
urlList ? [ "ldap:///" ],
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
create_ldap_user = pkgs.writeShellScriptBin "create_ldap_user" ''
|
||||||
|
# Base DN for LDAP directory
|
||||||
|
BASE_DN="dc=net,dc=dn"
|
||||||
|
# Organizational Unit (OU) where users are stored
|
||||||
|
OU="people"
|
||||||
|
|
||||||
|
# Prompt for username
|
||||||
|
read -p "Please enter the username: " USERNAME
|
||||||
|
|
||||||
|
# Prompt for password (hidden input)
|
||||||
|
read -s -p "Please enter the password: " USER_PASSWORD
|
||||||
|
echo
|
||||||
|
# Prompt for password confirmation (hidden input)
|
||||||
|
read -s -p "Please confirm the password: " USER_PASSWORD_CONFIRM
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if the entered passwords match
|
||||||
|
if [ "$USER_PASSWORD" != "$USER_PASSWORD_CONFIRM" ]; then
|
||||||
|
echo "❌ Passwords do not match. Please run the script again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Hash the password using slappasswd
|
||||||
|
PASSWORD_HASH=$(slappasswd -s "$USER_PASSWORD")
|
||||||
|
|
||||||
|
# Construct the Distinguished Name (DN) for the user
|
||||||
|
USER_DN="uid=$USERNAME,ou=$OU,$BASE_DN"
|
||||||
|
|
||||||
|
# Check if the base DN (dc=net,dc=dn) exists, if not, create it
|
||||||
|
ldapsearch -x -b "$BASE_DN" > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "⚠️ $BASE_DN does not exist. Creating it now..."
|
||||||
|
cat <<EOF | ldapadd -x -D "cn=admin,$BASE_DN" -W
|
||||||
|
dn: $BASE_DN
|
||||||
|
objectClass: top
|
||||||
|
objectClass: domain
|
||||||
|
dc: net
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the OU exists, if not, create it
|
||||||
|
ldapsearch -x -b "ou=$OU,$BASE_DN" > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "⚠️ OU=$OU does not exist. Creating it now..."
|
||||||
|
cat <<EOF | ldapadd -x -D "cn=admin,$BASE_DN" -W
|
||||||
|
dn: ou=$OU,$BASE_DN
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
ou: $OU
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add the user entry to the LDAP directory
|
||||||
|
cat <<EOF | ldapadd -x -D "cn=admin,$BASE_DN" -W
|
||||||
|
dn: $USER_DN
|
||||||
|
objectClass: inetOrgPerson
|
||||||
|
objectClass: organizationalPerson
|
||||||
|
objectClass: person
|
||||||
|
objectClass: top
|
||||||
|
uid: $USERNAME
|
||||||
|
cn: $USERNAME
|
||||||
|
sn: $USERNAME
|
||||||
|
userPassword: $PASSWORD_HASH
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Confirm the user was successfully created
|
||||||
|
echo "✅ User $USERNAME has been successfully created." '';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
environment.systemPackages = [
|
||||||
|
create_ldap_user
|
||||||
|
];
|
||||||
|
|
||||||
|
services.openldap = {
|
||||||
|
enable = true;
|
||||||
|
urlList = urlList;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
attrs = {
|
||||||
|
olcLogLevel = "conns config";
|
||||||
|
};
|
||||||
|
|
||||||
|
children = {
|
||||||
|
"cn=schema".includes = [
|
||||||
|
"${pkgs.openldap}/etc/schema/core.ldif"
|
||||||
|
"${pkgs.openldap}/etc/schema/cosine.ldif"
|
||||||
|
"${pkgs.openldap}/etc/schema/inetorgperson.ldif"
|
||||||
|
];
|
||||||
|
|
||||||
|
"olcDatabase={1}mdb".attrs = {
|
||||||
|
objectClass = [
|
||||||
|
"olcDatabaseConfig"
|
||||||
|
"olcMdbConfig"
|
||||||
|
];
|
||||||
|
|
||||||
|
olcDatabase = "{1}mdb";
|
||||||
|
olcDbDirectory = "/var/lib/openldap/data";
|
||||||
|
|
||||||
|
olcSuffix = "dc=net,dc=dn";
|
||||||
|
|
||||||
|
olcRootDN = "cn=admin,dc=net,dc=dn";
|
||||||
|
olcRootPW.path = config.sops.secrets."openldap/adminPassword".path;
|
||||||
|
|
||||||
|
olcAccess = [
|
||||||
|
# custom access rules for userPassword attributes
|
||||||
|
''
|
||||||
|
{0}to attrs=userPassword
|
||||||
|
by self write
|
||||||
|
by anonymous auth
|
||||||
|
by * none''
|
||||||
|
|
||||||
|
# allow read on anything else
|
||||||
|
''
|
||||||
|
{1}to *
|
||||||
|
by * read''
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -36,7 +36,10 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
set -gq allow-passthrough on
|
set -g allow-passthrough on
|
||||||
|
set -s set-clipboard on
|
||||||
|
set-option -s set-clipboard on
|
||||||
|
|
||||||
set -g status "on"
|
set -g status "on"
|
||||||
set -g status-style fg=default,bg=default
|
set -g status-style fg=default,bg=default
|
||||||
set -g status-position top
|
set -g status-position top
|
||||||
|
|
@ -48,7 +51,6 @@ in
|
||||||
setw -g window-status-format "#[fg=#171616,bg=default] #[fg=#495361,bg=default]#(${getIconScript}/get-icon #I) #W"
|
setw -g window-status-format "#[fg=#171616,bg=default] #[fg=#495361,bg=default]#(${getIconScript}/get-icon #I) #W"
|
||||||
setw -g window-status-current-format "#[fg=#7e93a9,bg=default] #[fg=#7e93a9,bg=default,bold]#(${getIconScript}/get-icon #I) #W"
|
setw -g window-status-current-format "#[fg=#7e93a9,bg=default] #[fg=#7e93a9,bg=default,bold]#(${getIconScript}/get-icon #I) #W"
|
||||||
|
|
||||||
|
|
||||||
set -g default-terminal "xterm-256color"
|
set -g default-terminal "xterm-256color"
|
||||||
set -ga terminal-overrides ",*256col*:Tc"
|
set -ga terminal-overrides ",*256col*:Tc"
|
||||||
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
|
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
|
||||||
|
|
|
||||||
32
system/modules/vaultwarden.nix
Normal file
32
system/modules/vaultwarden.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
{ domain }:
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "vaultwarden";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
ensureDatabases = [
|
||||||
|
"vaultwarden"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.vaultwarden = {
|
||||||
|
enable = true;
|
||||||
|
dbBackend = "postgresql";
|
||||||
|
environmentFile = config.sops.secrets.vaultwarden.path;
|
||||||
|
config = {
|
||||||
|
DOMAIN = domain;
|
||||||
|
SIGNUPS_ALLOWED = true;
|
||||||
|
SIGNUPS_VERIFY = true;
|
||||||
|
ROCKET_PORT = 8222;
|
||||||
|
ROCKET_ADDRESS = "127.0.0.1";
|
||||||
|
ROCKET_LOG = "critical";
|
||||||
|
|
||||||
|
DATABASE_URL = "postgresql:///vaultwarden";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue