server: reorganize
This commit is contained in:
parent
7535990be0
commit
598044863f
|
@ -102,6 +102,7 @@
|
||||||
package = pkgs.gitAndTools.gitFull;
|
package = pkgs.gitAndTools.gitFull;
|
||||||
delta.enable = true;
|
delta.enable = true;
|
||||||
extraConfig = {
|
extraConfig = {
|
||||||
|
commit.gpgsign = true;
|
||||||
# disable the atrocious gui password prompt
|
# disable the atrocious gui password prompt
|
||||||
core.askPass = "";
|
core.askPass = "";
|
||||||
# ...and prefer getting passwords from libsecret (and storing them there)
|
# ...and prefer getting passwords from libsecret (and storing them there)
|
||||||
|
|
|
@ -9,21 +9,32 @@ let
|
||||||
tsja = callPackage ./tsja.nix { };
|
tsja = callPackage ./tsja.nix { };
|
||||||
};
|
};
|
||||||
gen' = postgresql: builtins.mapAttrs (k: v: v.override { inherit postgresql; }) extraPackages;
|
gen' = postgresql: builtins.mapAttrs (k: v: v.override { inherit postgresql; }) extraPackages;
|
||||||
gen = ver: pkgs."postgresql${toString ver}Packages" // gen' pkgs."postgresql_${toString ver}";
|
gen = ver: pkgs."postgresql${toString ver}Packages" // gen' pkgs."postgresql${if ver == "" then "" else "_" + toString ver}";
|
||||||
in {
|
psql = ver: let
|
||||||
mecab = pkgs.mecab.overrideAttrs (old: {
|
old = pkgs."postgresql${if ver == "" then "" else "_" + toString ver}";
|
||||||
postInstall = ''
|
in old // { pkgs = old.pkgs // gen' old; };
|
||||||
mkdir -p $out/lib/mecab/dic
|
self = {
|
||||||
ln -s ${callPackage /${pkgs.path}/pkgs/tools/text/mecab/ipadic.nix {
|
mecab = pkgs.mecab.overrideAttrs (old: {
|
||||||
mecab-nodic = callPackage /${pkgs.path}/pkgs/tools/text/mecab/nodic.nix { };
|
postInstall = ''
|
||||||
}} $out/lib/mecab/dic/ipadic
|
mkdir -p $out/lib/mecab/dic
|
||||||
'';
|
ln -s ${callPackage /${pkgs.path}/pkgs/tools/text/mecab/ipadic.nix {
|
||||||
});
|
mecab-nodic = callPackage /${pkgs.path}/pkgs/tools/text/mecab/nodic.nix { };
|
||||||
postgresqlPackages = gen "";
|
}} $out/lib/mecab/dic/ipadic
|
||||||
postgresql11Packages = gen 11;
|
'';
|
||||||
postgresql12Packages = gen 12;
|
});
|
||||||
postgresql13Packages = gen 13;
|
postgresqlPackages = gen "";
|
||||||
postgresql14Packages = gen 14;
|
postgresql = psql "";
|
||||||
postgresql15Packages = gen 15;
|
postgresql11Packages = gen 11;
|
||||||
postgresql16Packages = gen 16;
|
postgresql_11 = psql 11;
|
||||||
}
|
postgresql12Packages = gen 12;
|
||||||
|
postgresql_12 = psql 12;
|
||||||
|
postgresql13Packages = gen 13;
|
||||||
|
postgresql_13 = psql 13;
|
||||||
|
postgresql14Packages = gen 14;
|
||||||
|
postgresql_14 = psql 14;
|
||||||
|
postgresql15Packages = gen 15;
|
||||||
|
postgresql_15 = psql 15;
|
||||||
|
postgresql16Packages = gen 16;
|
||||||
|
postgresql_16 = psql 16;
|
||||||
|
};
|
||||||
|
in self
|
||||||
|
|
78
system/hosts/server/akkoma.nix
Normal file
78
system/hosts/server/akkoma.nix
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
{ config
|
||||||
|
, pkgs
|
||||||
|
, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.server;
|
||||||
|
in {
|
||||||
|
# TODO: remove this in 2024
|
||||||
|
services.nginx.virtualHosts."pleroma.${cfg.domainName}" = {
|
||||||
|
quic = true;
|
||||||
|
enableACME = true;
|
||||||
|
addSSL = true;
|
||||||
|
serverAliases = [ "akkoma.${cfg.domainName}" ];
|
||||||
|
locations."/".return = "301 https://fedi.${cfg.domainName}$request_uri";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql.extraPlugins = with config.services.postgresql.package.pkgs; [ tsja ];
|
||||||
|
|
||||||
|
services.akkoma = {
|
||||||
|
enable = true;
|
||||||
|
dist.extraFlags = [
|
||||||
|
"+sbwt" "none"
|
||||||
|
"+sbwtdcpu" "none"
|
||||||
|
"+sbwtdio" "none"
|
||||||
|
];
|
||||||
|
config.":pleroma"."Pleroma.Web.Endpoint" = {
|
||||||
|
url = {
|
||||||
|
scheme = "https";
|
||||||
|
host = "fedi.${cfg.domainName}";
|
||||||
|
port = 443;
|
||||||
|
};
|
||||||
|
secret_key_base._secret = "/secrets/akkoma/secret_key_base";
|
||||||
|
signing_salt._secret = "/secrets/akkoma/signing_salt";
|
||||||
|
live_view.signing_salt._secret = "/secrets/akkoma/live_view_signing_salt";
|
||||||
|
};
|
||||||
|
initDb = {
|
||||||
|
enable = false;
|
||||||
|
username = "akkoma";
|
||||||
|
password._secret = "/secrets/akkoma/postgres_password";
|
||||||
|
};
|
||||||
|
config.":pleroma".":instance" = {
|
||||||
|
name = cfg.domainName;
|
||||||
|
description = "Insert instance description here";
|
||||||
|
email = "webmaster-akkoma@${cfg.domainName}";
|
||||||
|
notify_email = "noreply@${cfg.domainName}";
|
||||||
|
limit = 5000;
|
||||||
|
registrations_open = true;
|
||||||
|
account_activation_required = true;
|
||||||
|
account_approval_required = true;
|
||||||
|
};
|
||||||
|
config.":pleroma"."Pleroma.Repo" = {
|
||||||
|
adapter = (pkgs.formats.elixirConf { }).lib.mkRaw "Ecto.Adapters.Postgres";
|
||||||
|
username = "akkoma";
|
||||||
|
password._secret = "/secrets/akkoma/postgres_password";
|
||||||
|
database = "akkoma";
|
||||||
|
hostname = "localhost";
|
||||||
|
};
|
||||||
|
config.":web_push_encryption".":vapid_details" = {
|
||||||
|
subject = "mailto:webmaster-akkoma@${cfg.domainName}";
|
||||||
|
public_key._secret = "/secrets/akkoma/push_public_key";
|
||||||
|
private_key._secret = "/secrets/akkoma/push_private_key";
|
||||||
|
};
|
||||||
|
config.":joken".":default_signer"._secret = "/secrets/akkoma/joken_signer";
|
||||||
|
nginx = {
|
||||||
|
quic = true;
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
systemd.services.akkoma = {
|
||||||
|
path = [ pkgs.exiftool pkgs.gawk ];
|
||||||
|
serviceConfig.Restart = "on-failure";
|
||||||
|
unitConfig = {
|
||||||
|
StartLimitIntervalSec = 60;
|
||||||
|
StartLimitBurst = 3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
44
system/hosts/server/certspotter.nix
Normal file
44
system/hosts/server/certspotter.nix
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{ config
|
||||||
|
, lib
|
||||||
|
, pkgs
|
||||||
|
, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.server;
|
||||||
|
in {
|
||||||
|
security.acme.certs = lib.flip builtins.mapAttrs (lib.filterAttrs (k: v: v.enableACME) config.services.nginx.virtualHosts) (k: v: {
|
||||||
|
postRun = let
|
||||||
|
python = pkgs.python3.withPackages (p: with p; [ cryptography pyasn1 pyasn1-modules ]);
|
||||||
|
tbs-hash = pkgs.writeScript "tbs-hash.py" ''
|
||||||
|
#!${python}/bin/python3
|
||||||
|
import hashlib
|
||||||
|
from pyasn1.codec.der.decoder import decode
|
||||||
|
from pyasn1.codec.der.encoder import encode
|
||||||
|
from pyasn1_modules import rfc5280
|
||||||
|
from cryptography import x509
|
||||||
|
|
||||||
|
with open('full.pem', 'rb') as f:
|
||||||
|
cert = x509.load_pem_x509_certificate(f.read())
|
||||||
|
tbs, _leftover = decode(cert.tbs_certificate_bytes, asn1Spec=rfc5280.TBSCertificate())
|
||||||
|
precert_exts = [v.dotted_string for k, v in x509.ExtensionOID.__dict__.items() if k.startswith('PRECERT_')]
|
||||||
|
exts = [ext for ext in tbs["extensions"] if str(ext["extnID"]) not in precert_exts]
|
||||||
|
tbs["extensions"].clear()
|
||||||
|
tbs["extensions"].extend(exts)
|
||||||
|
print(hashlib.sha256(encode(tbs)).hexdigest())
|
||||||
|
'';
|
||||||
|
in ''
|
||||||
|
${tbs-hash} > "/var/lib/certspotter/tbs-hashes/${k}"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
services.certspotter = {
|
||||||
|
enable = true;
|
||||||
|
extraFlags = [ ];
|
||||||
|
watchlist = [ ".pavluk.org" ];
|
||||||
|
hooks = lib.toList (pkgs.writeShellScript "certspotter-hook" ''
|
||||||
|
if [[ "$EVENT" == discovered_cert ]]; then
|
||||||
|
${pkgs.gnugrep}/bin/grep -r "$TBS_SHA256" /var/lib/certspotter/tbs-hashes/ && exit
|
||||||
|
fi
|
||||||
|
(echo "Subject: $SUMMARY" && echo && cat "$TEXT_FILENAME") | /run/wrappers/bin/sendmail -i webmaster-certspotter@${cfg.domainName}
|
||||||
|
'');
|
||||||
|
};
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
let
|
let
|
||||||
cfg = config.server;
|
cfg = config.server;
|
||||||
|
|
||||||
hosted-domains =
|
hostedDomains =
|
||||||
builtins.concatLists
|
builtins.concatLists
|
||||||
(builtins.attrValues
|
(builtins.attrValues
|
||||||
(builtins.mapAttrs
|
(builtins.mapAttrs
|
||||||
|
@ -15,12 +15,16 @@ let
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
./options.nix
|
./options.nix
|
||||||
./matrix.nix
|
./akkoma.nix
|
||||||
|
./certspotter.nix
|
||||||
./fdroid.nix
|
./fdroid.nix
|
||||||
./mumble.nix
|
./files.nix
|
||||||
./mailserver.nix
|
|
||||||
./home.nix
|
./home.nix
|
||||||
./keycloak.nix
|
./keycloak.nix
|
||||||
|
./mailserver.nix
|
||||||
|
./matrix.nix
|
||||||
|
./mumble.nix
|
||||||
|
./searxng.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
system.stateVersion = "22.11";
|
system.stateVersion = "22.11";
|
||||||
|
@ -77,12 +81,11 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# just in case
|
# just in case
|
||||||
networking.hosts."127.0.0.1" = hosted-domains;
|
networking.hosts."127.0.0.1" = hostedDomains;
|
||||||
networking.hosts."::1" = hosted-domains;
|
networking.hosts."::1" = hostedDomains;
|
||||||
|
|
||||||
services.postgresql.enable = true;
|
services.postgresql.enable = true;
|
||||||
services.postgresql.package = pkgs.postgresql_13;
|
services.postgresql.package = pkgs.postgresql_13;
|
||||||
services.postgresql.extraPlugins = with pkgs.postgresql13Packages; [ tsja ];
|
|
||||||
|
|
||||||
# SSH
|
# SSH
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
|
@ -97,56 +100,6 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# SEARXNG
|
|
||||||
services.searx.enable = true;
|
|
||||||
services.searx.package = pkgs.searxng;
|
|
||||||
services.searx.runInUwsgi = true;
|
|
||||||
services.searx.uwsgiConfig = let inherit (config.services.searx) settings; in {
|
|
||||||
socket = "${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
|
||||||
};
|
|
||||||
services.searx.environmentFile = /var/lib/searx/searx.env;
|
|
||||||
services.searx.settings = {
|
|
||||||
use_default_settings = true;
|
|
||||||
search = {
|
|
||||||
safe_search = 0;
|
|
||||||
autocomplete = "duckduckgo"; # dbpedia, duckduckgo, google, startpage, swisscows, qwant, wikipedia - leave blank to turn off
|
|
||||||
default_lang = ""; # leave blank to detect from browser info or use codes from languages.py
|
|
||||||
};
|
|
||||||
|
|
||||||
server = {
|
|
||||||
port = 8888;
|
|
||||||
bind_address = "::1";
|
|
||||||
secret_key = "@SEARX_SECRET_KEY@";
|
|
||||||
base_url = "https://search.${cfg.domainName}/";
|
|
||||||
image_proxy = true;
|
|
||||||
default_http_headers = {
|
|
||||||
X-Content-Type-Options = "nosniff";
|
|
||||||
X-XSS-Protection = "1; mode=block";
|
|
||||||
X-Download-Options = "noopen";
|
|
||||||
X-Robots-Tag = "noindex, nofollow";
|
|
||||||
Referrer-Policy = "no-referrer";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
outgoing = {
|
|
||||||
request_timeout = 5.0; # default timeout in seconds, can be override by engine
|
|
||||||
max_request_timeout = 15.0; # the maximum timeout in seconds
|
|
||||||
pool_connections = 100; # Maximum number of allowable connections, or null
|
|
||||||
pool_maxsize = 10; # Number of allowable keep-alive connections, or null
|
|
||||||
enable_http2 = true; # See https://www.python-httpx.org/http2/
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."search.${cfg.domainName}" = let inherit (config.services.searx) settings; in {
|
|
||||||
quic = true;
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
# locations."/".proxyPass = "http://${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
|
||||||
locations."/".extraConfig = ''
|
|
||||||
uwsgi_pass "${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
|
||||||
include ${config.services.nginx.package}/conf/uwsgi_params;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# NGINX
|
# NGINX
|
||||||
services.nginx.enable = true;
|
services.nginx.enable = true;
|
||||||
services.nginx.enableReload = true;
|
services.nginx.enableReload = true;
|
||||||
|
@ -212,188 +165,6 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# GITEA
|
|
||||||
services.nginx.virtualHosts."git.${cfg.domainName}" = let inherit (config.services.gitea) settings; in {
|
|
||||||
quic = true;
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
locations."/".proxyPass = "http://${lib.quoteListenAddr settings.server.HTTP_ADDR}:${toString settings.server.HTTP_PORT}";
|
|
||||||
};
|
|
||||||
services.gitea = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.forgejo;
|
|
||||||
database = {
|
|
||||||
createDatabase = false;
|
|
||||||
passwordFile = "/var/lib/gitea/db_password";
|
|
||||||
type = "postgres";
|
|
||||||
};
|
|
||||||
settings = {
|
|
||||||
federation.ENABLED = true;
|
|
||||||
"git.timeout" = {
|
|
||||||
DEFAULT = 6000;
|
|
||||||
MIGRATE = 60000;
|
|
||||||
MIRROR = 60000;
|
|
||||||
GC = 120;
|
|
||||||
};
|
|
||||||
mailer = {
|
|
||||||
ENABLED = true;
|
|
||||||
FROM = "Forgejo <noreply@${cfg.domainName}>";
|
|
||||||
PROTOCOL = "smtp";
|
|
||||||
SMTP_ADDR = "mail.${cfg.domainName}";
|
|
||||||
SMTP_PORT = 587;
|
|
||||||
USER = "noreply@${cfg.domainName}";
|
|
||||||
PASSWD = cfg.unhashedNoreplyPassword;
|
|
||||||
FORCE_TRUST_SERVER_CERT = true;
|
|
||||||
};
|
|
||||||
session = {
|
|
||||||
COOKIE_SECURE = true;
|
|
||||||
};
|
|
||||||
server = {
|
|
||||||
ROOT_URL = "https://git.${cfg.domainName}";
|
|
||||||
HTTP_ADDR = "::1";
|
|
||||||
HTTP_PORT = 3310;
|
|
||||||
DOMAIN = "git.${cfg.domainName}";
|
|
||||||
# START_SSH_SERVER = true;
|
|
||||||
# SSH_PORT = 2222;
|
|
||||||
};
|
|
||||||
service = {
|
|
||||||
DISABLE_REGISTRATION = true;
|
|
||||||
REGISTER_EMAIL_CONFIRM = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# NEXTCLOUD
|
|
||||||
services.nginx.virtualHosts."cloud.${cfg.domainName}" = {
|
|
||||||
quic = true;
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
};
|
|
||||||
services.nextcloud = {
|
|
||||||
enable = true;
|
|
||||||
enableBrokenCiphersForSSE = false;
|
|
||||||
package = pkgs.nextcloud27;
|
|
||||||
autoUpdateApps.enable = true;
|
|
||||||
# TODO: use socket auth and remove the next line
|
|
||||||
database.createLocally = false;
|
|
||||||
config = {
|
|
||||||
adminpassFile = "/var/lib/nextcloud/admin_password";
|
|
||||||
dbpassFile = "/var/lib/nextcloud/db_password";
|
|
||||||
dbtype = "pgsql";
|
|
||||||
dbhost = "/run/postgresql";
|
|
||||||
overwriteProtocol = "https";
|
|
||||||
};
|
|
||||||
hostName = "cloud.${cfg.domainName}";
|
|
||||||
https = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# AKKOMA
|
|
||||||
# TODO: remove this in 2024
|
|
||||||
services.nginx.virtualHosts."pleroma.${cfg.domainName}" = {
|
|
||||||
quic = true;
|
|
||||||
enableACME = true;
|
|
||||||
addSSL = true;
|
|
||||||
serverAliases = [ "akkoma.${cfg.domainName}" ];
|
|
||||||
locations."/".return = "301 https://fedi.${cfg.domainName}$request_uri";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.akkoma = {
|
|
||||||
enable = true;
|
|
||||||
dist.extraFlags = [
|
|
||||||
"+sbwt" "none"
|
|
||||||
"+sbwtdcpu" "none"
|
|
||||||
"+sbwtdio" "none"
|
|
||||||
];
|
|
||||||
config.":pleroma"."Pleroma.Web.Endpoint" = {
|
|
||||||
url = {
|
|
||||||
scheme = "https";
|
|
||||||
host = "fedi.${cfg.domainName}";
|
|
||||||
port = 443;
|
|
||||||
};
|
|
||||||
secret_key_base._secret = "/secrets/akkoma/secret_key_base";
|
|
||||||
signing_salt._secret = "/secrets/akkoma/signing_salt";
|
|
||||||
live_view.signing_salt._secret = "/secrets/akkoma/live_view_signing_salt";
|
|
||||||
};
|
|
||||||
initDb = {
|
|
||||||
enable = false;
|
|
||||||
username = "akkoma";
|
|
||||||
password._secret = "/secrets/akkoma/postgres_password";
|
|
||||||
};
|
|
||||||
config.":pleroma".":instance" = {
|
|
||||||
name = cfg.domainName;
|
|
||||||
description = "Insert instance description here";
|
|
||||||
email = "webmaster-akkoma@${cfg.domainName}";
|
|
||||||
notify_email = "noreply@${cfg.domainName}";
|
|
||||||
limit = 5000;
|
|
||||||
registrations_open = true;
|
|
||||||
account_activation_required = true;
|
|
||||||
account_approval_required = true;
|
|
||||||
};
|
|
||||||
config.":pleroma"."Pleroma.Repo" = {
|
|
||||||
adapter = (pkgs.formats.elixirConf { }).lib.mkRaw "Ecto.Adapters.Postgres";
|
|
||||||
username = "akkoma";
|
|
||||||
password._secret = "/secrets/akkoma/postgres_password";
|
|
||||||
database = "akkoma";
|
|
||||||
hostname = "localhost";
|
|
||||||
};
|
|
||||||
config.":web_push_encryption".":vapid_details" = {
|
|
||||||
subject = "mailto:webmaster-akkoma@${cfg.domainName}";
|
|
||||||
public_key._secret = "/secrets/akkoma/push_public_key";
|
|
||||||
private_key._secret = "/secrets/akkoma/push_private_key";
|
|
||||||
};
|
|
||||||
config.":joken".":default_signer"._secret = "/secrets/akkoma/joken_signer";
|
|
||||||
nginx = {
|
|
||||||
quic = true;
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
systemd.services.akkoma = {
|
|
||||||
path = [ pkgs.exiftool pkgs.gawk ];
|
|
||||||
serviceConfig.Restart = "on-failure";
|
|
||||||
unitConfig = {
|
|
||||||
StartLimitIntervalSec = 60;
|
|
||||||
StartLimitBurst = 3;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# TODO: calc tbs instead of pubkey hash?
|
|
||||||
security.acme.certs = lib.flip builtins.mapAttrs (lib.filterAttrs (k: v: v.enableACME) config.services.nginx.virtualHosts) (k: v: {
|
|
||||||
postRun = let
|
|
||||||
python = pkgs.python3.withPackages (p: with p; [ cryptography pyasn1 pyasn1-modules ]);
|
|
||||||
tbs-hash = pkgs.writeScript "tbs-hash.py" ''
|
|
||||||
#!${python}/bin/python3
|
|
||||||
import hashlib
|
|
||||||
from pyasn1.codec.der.decoder import decode
|
|
||||||
from pyasn1.codec.der.encoder import encode
|
|
||||||
from pyasn1_modules import rfc5280
|
|
||||||
from cryptography import x509
|
|
||||||
|
|
||||||
with open('full.pem', 'rb') as f:
|
|
||||||
cert = x509.load_pem_x509_certificate(f.read())
|
|
||||||
tbs, _leftover = decode(cert.tbs_certificate_bytes, asn1Spec=rfc5280.TBSCertificate())
|
|
||||||
precert_exts = [v.dotted_string for k, v in x509.ExtensionOID.__dict__.items() if k.startswith('PRECERT_')]
|
|
||||||
exts = [ext for ext in tbs["extensions"] if str(ext["extnID"]) not in precert_exts]
|
|
||||||
tbs["extensions"].clear()
|
|
||||||
tbs["extensions"].extend(exts)
|
|
||||||
print(hashlib.sha256(encode(tbs)).hexdigest())
|
|
||||||
'';
|
|
||||||
in ''
|
|
||||||
${tbs-hash} > "/var/lib/certspotter/tbs-hashes/${k}"
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
services.certspotter = {
|
|
||||||
enable = true;
|
|
||||||
extraFlags = [ ];
|
|
||||||
watchlist = [ ".pavluk.org" ];
|
|
||||||
hooks = lib.toList (pkgs.writeShellScript "certspotter-hook" ''
|
|
||||||
if [[ "$EVENT" == discovered_cert ]]; then
|
|
||||||
${pkgs.gnugrep}/bin/grep -r "$TBS_SHA256" /var/lib/certspotter/tbs-hashes/ && exit
|
|
||||||
fi
|
|
||||||
(echo "Subject: $SUMMARY" && echo && cat "$TEXT_FILENAME") | /run/wrappers/bin/sendmail -i webmaster-certspotter@${cfg.domainName}
|
|
||||||
'');
|
|
||||||
};
|
|
||||||
|
|
||||||
/*locations."/dns-query".extraConfig = ''
|
/*locations."/dns-query".extraConfig = ''
|
||||||
grpc_pass grpc://127.0.0.1:53453;
|
grpc_pass grpc://127.0.0.1:53453;
|
||||||
'';*/
|
'';*/
|
||||||
|
|
83
system/hosts/server/files.nix
Normal file
83
system/hosts/server/files.nix
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
{ config
|
||||||
|
, lib
|
||||||
|
, pkgs
|
||||||
|
, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.server;
|
||||||
|
in {
|
||||||
|
services.nginx.virtualHosts."git.${cfg.domainName}" = let inherit (config.services.forgejo) settings; in {
|
||||||
|
quic = true;
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/".proxyPass = "http://${lib.quoteListenAddr settings.server.HTTP_ADDR}:${toString settings.server.HTTP_PORT}";
|
||||||
|
};
|
||||||
|
services.forgejo = {
|
||||||
|
enable = true;
|
||||||
|
database = {
|
||||||
|
createDatabase = false;
|
||||||
|
type = "postgres";
|
||||||
|
user = "gitea";
|
||||||
|
name = "gitea";
|
||||||
|
passwordFile = "/secrets/forgejo_db_password";
|
||||||
|
};
|
||||||
|
lfs.enable = true;
|
||||||
|
settings = {
|
||||||
|
federation.ENABLED = true;
|
||||||
|
"git.timeout" = {
|
||||||
|
DEFAULT = 6000;
|
||||||
|
MIGRATE = 60000;
|
||||||
|
MIRROR = 60000;
|
||||||
|
GC = 120;
|
||||||
|
};
|
||||||
|
mailer = {
|
||||||
|
ENABLED = true;
|
||||||
|
FROM = "Forgejo <noreply@${cfg.domainName}>";
|
||||||
|
PROTOCOL = "smtp";
|
||||||
|
SMTP_ADDR = "mail.${cfg.domainName}";
|
||||||
|
SMTP_PORT = 587;
|
||||||
|
USER = "noreply@${cfg.domainName}";
|
||||||
|
PASSWD = cfg.unhashedNoreplyPassword;
|
||||||
|
FORCE_TRUST_SERVER_CERT = true;
|
||||||
|
};
|
||||||
|
session = {
|
||||||
|
COOKIE_SECURE = true;
|
||||||
|
};
|
||||||
|
server = {
|
||||||
|
ROOT_URL = "https://git.${cfg.domainName}";
|
||||||
|
HTTP_ADDR = "::1";
|
||||||
|
HTTP_PORT = 3310;
|
||||||
|
DOMAIN = "git.${cfg.domainName}";
|
||||||
|
# START_SSH_SERVER = true;
|
||||||
|
# SSH_PORT = 2222;
|
||||||
|
};
|
||||||
|
service = {
|
||||||
|
DISABLE_REGISTRATION = true;
|
||||||
|
REGISTER_EMAIL_CONFIRM = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."cloud.${cfg.domainName}" = {
|
||||||
|
quic = true;
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
};
|
||||||
|
services.nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
enableBrokenCiphersForSSE = false;
|
||||||
|
package = pkgs.nextcloud27;
|
||||||
|
autoUpdateApps.enable = true;
|
||||||
|
# TODO: use socket auth and remove the next line
|
||||||
|
database.createLocally = false;
|
||||||
|
config = {
|
||||||
|
adminpassFile = "/var/lib/nextcloud/admin_password";
|
||||||
|
dbpassFile = "/var/lib/nextcloud/db_password";
|
||||||
|
dbtype = "pgsql";
|
||||||
|
dbhost = "/run/postgresql";
|
||||||
|
overwriteProtocol = "https";
|
||||||
|
};
|
||||||
|
hostName = "cloud.${cfg.domainName}";
|
||||||
|
https = true;
|
||||||
|
};
|
||||||
|
}
|
58
system/hosts/server/forgejo.nix
Normal file
58
system/hosts/server/forgejo.nix
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{ config
|
||||||
|
, lib
|
||||||
|
, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.server;
|
||||||
|
in {
|
||||||
|
services.nginx.virtualHosts."git.${cfg.domainName}" = let inherit (config.services.forgejo) settings; in {
|
||||||
|
quic = true;
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/".proxyPass = "http://${lib.quoteListenAddr settings.server.HTTP_ADDR}:${toString settings.server.HTTP_PORT}";
|
||||||
|
};
|
||||||
|
services.forgejo = {
|
||||||
|
enable = true;
|
||||||
|
database = {
|
||||||
|
createDatabase = false;
|
||||||
|
user = "gitea";
|
||||||
|
passwordFile = "/secrets/forgejo_db_password";
|
||||||
|
type = "postgres";
|
||||||
|
};
|
||||||
|
lfs.enable = true;
|
||||||
|
settings = {
|
||||||
|
federation.ENABLED = true;
|
||||||
|
"git.timeout" = {
|
||||||
|
DEFAULT = 6000;
|
||||||
|
MIGRATE = 60000;
|
||||||
|
MIRROR = 60000;
|
||||||
|
GC = 120;
|
||||||
|
};
|
||||||
|
mailer = {
|
||||||
|
ENABLED = true;
|
||||||
|
FROM = "Forgejo <noreply@${cfg.domainName}>";
|
||||||
|
PROTOCOL = "smtp";
|
||||||
|
SMTP_ADDR = "mail.${cfg.domainName}";
|
||||||
|
SMTP_PORT = 587;
|
||||||
|
USER = "noreply@${cfg.domainName}";
|
||||||
|
PASSWD = cfg.unhashedNoreplyPassword;
|
||||||
|
FORCE_TRUST_SERVER_CERT = true;
|
||||||
|
};
|
||||||
|
session = {
|
||||||
|
COOKIE_SECURE = true;
|
||||||
|
};
|
||||||
|
server = {
|
||||||
|
ROOT_URL = "https://git.${cfg.domainName}";
|
||||||
|
HTTP_ADDR = "::1";
|
||||||
|
HTTP_PORT = 3310;
|
||||||
|
DOMAIN = "git.${cfg.domainName}";
|
||||||
|
# START_SSH_SERVER = true;
|
||||||
|
# SSH_PORT = 2222;
|
||||||
|
};
|
||||||
|
service = {
|
||||||
|
DISABLE_REGISTRATION = false;
|
||||||
|
REGISTER_MANUAL_CONFIRM = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
57
system/hosts/server/searxng.nix
Normal file
57
system/hosts/server/searxng.nix
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{ config
|
||||||
|
, lib
|
||||||
|
, pkgs
|
||||||
|
, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.server;
|
||||||
|
in {
|
||||||
|
services.nginx.virtualHosts."search.${cfg.domainName}" = let inherit (config.services.searx) settings; in {
|
||||||
|
quic = true;
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
# locations."/".proxyPass = "http://${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
||||||
|
locations."/".extraConfig = ''
|
||||||
|
uwsgi_pass "${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
||||||
|
include ${config.services.nginx.package}/conf/uwsgi_params;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.searx.enable = true;
|
||||||
|
services.searx.package = pkgs.searxng;
|
||||||
|
services.searx.runInUwsgi = true;
|
||||||
|
services.searx.uwsgiConfig = let inherit (config.services.searx) settings; in {
|
||||||
|
socket = "${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
||||||
|
};
|
||||||
|
services.searx.environmentFile = /var/lib/searx/searx.env;
|
||||||
|
services.searx.settings = {
|
||||||
|
use_default_settings = true;
|
||||||
|
search = {
|
||||||
|
safe_search = 0;
|
||||||
|
autocomplete = "duckduckgo"; # dbpedia, duckduckgo, google, startpage, swisscows, qwant, wikipedia - leave blank to turn off
|
||||||
|
default_lang = ""; # leave blank to detect from browser info or use codes from languages.py
|
||||||
|
};
|
||||||
|
|
||||||
|
server = {
|
||||||
|
port = 8888;
|
||||||
|
bind_address = "::1";
|
||||||
|
secret_key = "@SEARX_SECRET_KEY@";
|
||||||
|
base_url = "https://search.${cfg.domainName}/";
|
||||||
|
image_proxy = true;
|
||||||
|
default_http_headers = {
|
||||||
|
X-Content-Type-Options = "nosniff";
|
||||||
|
X-XSS-Protection = "1; mode=block";
|
||||||
|
X-Download-Options = "noopen";
|
||||||
|
X-Robots-Tag = "noindex, nofollow";
|
||||||
|
Referrer-Policy = "no-referrer";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
outgoing = {
|
||||||
|
request_timeout = 5.0; # default timeout in seconds, can be override by engine
|
||||||
|
max_request_timeout = 15.0; # the maximum timeout in seconds
|
||||||
|
pool_connections = 100; # Maximum number of allowable connections, or null
|
||||||
|
pool_maxsize = 10; # Number of allowable keep-alive connections, or null
|
||||||
|
enable_http2 = true; # See https://www.python-httpx.org/http2/
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -75,6 +75,8 @@ in {
|
||||||
{ directory = /var/db/dhcpcd; user = "root"; group = "root"; mode = "0755"; }
|
{ directory = /var/db/dhcpcd; user = "root"; group = "root"; mode = "0755"; }
|
||||||
] ++ lib.optionals config.services.gitea.enable [
|
] ++ lib.optionals config.services.gitea.enable [
|
||||||
{ directory = /var/lib/gitea; user = "gitea"; group = "gitea"; mode = "0755"; }
|
{ directory = /var/lib/gitea; user = "gitea"; group = "gitea"; mode = "0755"; }
|
||||||
|
] ++ lib.optionals config.services.forgejo.enable [
|
||||||
|
{ directory = /var/lib/forgejo; user = "forgejo"; group = "forgejo"; mode = "0755"; }
|
||||||
] ++ lib.optionals config.services.matrix-synapse.enable [
|
] ++ lib.optionals config.services.matrix-synapse.enable [
|
||||||
{ directory = /var/lib/matrix-synapse; user = "matrix-synapse"; group = "matrix-synapse"; mode = "0700"; }
|
{ directory = /var/lib/matrix-synapse; user = "matrix-synapse"; group = "matrix-synapse"; mode = "0700"; }
|
||||||
] ++ lib.optionals config.services.heisenbridge.enable [
|
] ++ lib.optionals config.services.heisenbridge.enable [
|
||||||
|
|
Loading…
Reference in a new issue