treewide: move nixos modules
This commit is contained in:
parent
d84be7c616
commit
8eff4c5e4f
73 changed files with 62 additions and 62 deletions
42
modules/nixos/services/accentor/default.nix
Normal file
42
modules/nixos/services/accentor/default.nix
Normal file
|
@ -0,0 +1,42 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.accentor.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.accentor.enable {
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
};
|
||||
|
||||
services.accentor = {
|
||||
enable = true;
|
||||
home = "${config.chvp.dataPrefix}/var/lib/accentor";
|
||||
hostname = "accentor.vanpetegem.me";
|
||||
environmentFile = config.age.secrets."passwords/services/accentor".path;
|
||||
rescanTimer = {
|
||||
enable = true;
|
||||
dates = "00:00";
|
||||
};
|
||||
nginx = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "vanpetegem.me";
|
||||
};
|
||||
};
|
||||
|
||||
security.doas.extraRules = [{
|
||||
users = [ "charlotte" ];
|
||||
noPass = true;
|
||||
cmd = "accentor-console";
|
||||
runAs = "accentor";
|
||||
}];
|
||||
|
||||
age.secrets."passwords/services/accentor" = {
|
||||
file = ../../../../secrets/passwords/services/accentor.age;
|
||||
owner = "accentor";
|
||||
};
|
||||
};
|
||||
}
|
21
modules/nixos/services/containers/default.nix
Normal file
21
modules/nixos/services/containers/default.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.containers = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
externalInterface = lib.mkOption {
|
||||
example = "eno3";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
networking.nat = lib.mkIf config.chvp.services.containers.enable {
|
||||
enable = true;
|
||||
enableIPv6 = true;
|
||||
internalInterfaces = [ "ve-+" ];
|
||||
externalInterface = config.chvp.services.containers.externalInterface;
|
||||
};
|
||||
};
|
||||
}
|
46
modules/nixos/services/data-access/config.nix
Normal file
46
modules/nixos/services/data-access/config.nix
Normal file
|
@ -0,0 +1,46 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
users.users.data = {
|
||||
isNormalUser = true;
|
||||
home = "/home/data";
|
||||
description = "Data Access";
|
||||
uid = 1000;
|
||||
group = "users";
|
||||
hashedPasswordFile = "/run/secrets/password_file";
|
||||
};
|
||||
users.users.readonly = {
|
||||
isNormalUser = true;
|
||||
home = "/home/readonly";
|
||||
description = "Readonly data access";
|
||||
uid = 1001;
|
||||
group = "sftponly";
|
||||
hashedPasswordFile = "/run/secrets/readonly_password_file";
|
||||
};
|
||||
users.groups.sftponly = { gid = 10000; };
|
||||
environment.systemPackages = [ pkgs.rsync pkgs.mktorrent (pkgs.writeShellScriptBin "create_torrent" ". /run/secrets/create_torrent") ];
|
||||
security.sudo.enable = false;
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
hostKeys = [
|
||||
{ bits = 4096; path = "/run/secrets/ssh_host_rsa_key"; type = "rsa"; }
|
||||
{ path = "/run/secrets/ssh_host_ed25519_key"; type = "ed25519"; }
|
||||
];
|
||||
settings = {
|
||||
HostKeyAlgorithms = "+ssh-rsa";
|
||||
Macs = [ "hmac-sha2-512-etm@openssh.com" "hmac-sha2-256-etm@openssh.com" "umac-128-etm@openssh.com" "hmac-sha2-512" ];
|
||||
PermitRootLogin = "no";
|
||||
};
|
||||
extraConfig = ''
|
||||
Match group sftponly
|
||||
X11Forwarding no
|
||||
AllowTcpForwarding no
|
||||
AllowAgentForwarding no
|
||||
ForceCommand internal-sftp
|
||||
Match user data
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
'';
|
||||
authorizedKeysFiles = [ "/run/secrets/%u_authorized_keys" ];
|
||||
};
|
||||
}
|
122
modules/nixos/services/data-access/default.nix
Normal file
122
modules/nixos/services/data-access/default.nix
Normal file
|
@ -0,0 +1,122 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.data-access.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.data-access.enable {
|
||||
chvp.services = {
|
||||
containers.enable = true;
|
||||
nginx.hosts = [
|
||||
{
|
||||
fqdn = "data.vanpetegem.me";
|
||||
options = {
|
||||
default = true;
|
||||
basicAuthFile = config.age.secrets."passwords/services/data-basic-auth".path;
|
||||
root = "/srv/data";
|
||||
locations = {
|
||||
"/".extraConfig = ''
|
||||
autoindex on;
|
||||
'';
|
||||
"/public".extraConfig = ''
|
||||
autoindex on;
|
||||
auth_basic off;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 2002 ];
|
||||
|
||||
containers.data-access = {
|
||||
ephemeral = true;
|
||||
autoStart = true;
|
||||
bindMounts = {
|
||||
"/home/data/data" = {
|
||||
hostPath = "/srv/data";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/home/readonly/data" = {
|
||||
hostPath = "/srv/data";
|
||||
isReadOnly = true;
|
||||
};
|
||||
"/run/secrets" = {
|
||||
hostPath = "/run/data-access";
|
||||
isReadOnly = true;
|
||||
};
|
||||
};
|
||||
forwardPorts = [{
|
||||
containerPort = 22;
|
||||
hostPort = 2002;
|
||||
protocol = "tcp";
|
||||
}];
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.10";
|
||||
hostAddress6 = "fc00::1";
|
||||
localAddress = "192.168.100.11";
|
||||
localAddress6 = "fc00::2";
|
||||
config = { ... }: {
|
||||
system.stateVersion = config.chvp.stateVersion;
|
||||
imports = [ ./config.nix ];
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."data-access/ssh_host_rsa_key" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_rsa_key.age;
|
||||
path = "/run/data-access/ssh_host_rsa_key";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/ssh_host_rsa_key.pub" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_rsa_key.pub.age;
|
||||
path = "/run/data-access/ssh_host_rsa_key.pub";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/ssh_host_ed25519_key" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_ed25519_key.age;
|
||||
path = "/run/data-access/ssh_host_ed25519_key";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/ssh_host_ed25519_key.pub" = {
|
||||
file = ../../../../secrets/data-access/ssh_host_ed25519_key.pub.age;
|
||||
path = "/run/data-access/ssh_host_ed25519_key.pub";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/password_file" = {
|
||||
file = ../../../../secrets/data-access/password_file.age;
|
||||
path = "/run/data-access/password_file";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/readonly_password_file" = {
|
||||
file = ../../../../secrets/data-access/readonly_password_file.age;
|
||||
path = "/run/data-access/readonly_password_file";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/authorized_keys" = {
|
||||
file = ../../../../secrets/data-access/authorized_keys.age;
|
||||
owner = "charlotte";
|
||||
path = "/run/data-access/data_authorized_keys";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/readonly_authorized_keys" = {
|
||||
file = ../../../../secrets/data-access/readonly_authorized_keys.age;
|
||||
owner = "1001";
|
||||
group = "65534";
|
||||
path = "/run/data-access/readonly_authorized_keys";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."data-access/create_torrent" = {
|
||||
file = ../../../../secrets/data-access/create_torrent.age;
|
||||
owner = "charlotte";
|
||||
path = "/run/data-access/create_torrent";
|
||||
symlink = false;
|
||||
};
|
||||
age.secrets."passwords/services/data-basic-auth" = {
|
||||
file = ../../../../secrets/passwords/services/data-basic-auth.age;
|
||||
owner = "nginx";
|
||||
};
|
||||
};
|
||||
}
|
20
modules/nixos/services/default.nix
Normal file
20
modules/nixos/services/default.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./accentor
|
||||
./containers
|
||||
./data-access
|
||||
./garmin-scraper
|
||||
./git
|
||||
./grafana
|
||||
./mail
|
||||
./mastodon
|
||||
./matrix
|
||||
./nextcloud
|
||||
./nginx
|
||||
./torrents
|
||||
];
|
||||
|
||||
services.postgresql.package = pkgs.postgresql_15;
|
||||
}
|
39
modules/nixos/services/garmin-scraper/default.nix
Normal file
39
modules/nixos/services/garmin-scraper/default.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
garmin2influx = pkgs.writers.writePython3Bin "garmin2influx"
|
||||
{
|
||||
libraries = with pkgs.python3Packages; [ garminconnect influxdb-client ];
|
||||
}
|
||||
(builtins.readFile ./garmin2influx.py);
|
||||
in
|
||||
{
|
||||
options.chvp.services.garmin-scraper.enable = lib.mkEnableOption "garmin scraper";
|
||||
|
||||
config = lib.mkIf config.chvp.services.garmin-scraper.enable {
|
||||
# Install in environment to allow manual data collection
|
||||
environment.systemPackages = [ garmin2influx ];
|
||||
systemd = {
|
||||
services.garmin2influx = {
|
||||
description = "Garmin health data importer";
|
||||
restartIfChanged = false;
|
||||
unitConfig.X-StopOnRemoval = false;
|
||||
serviceConfig = {
|
||||
EnvironmentFile = config.age.secrets."passwords/services/garmin2influx-env".path;
|
||||
Type = "oneshot";
|
||||
User = "charlotte";
|
||||
Group = "users";
|
||||
ExecStart = "${garmin2influx}/bin/garmin2influx";
|
||||
RestartSec = "5s";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
startAt = "02/4:00";
|
||||
};
|
||||
timers.garmin2influx.timerConfig.RandomizedDelaySec = "30min";
|
||||
};
|
||||
age.secrets."passwords/services/garmin2influx-env" = {
|
||||
file = ../../../../secrets/passwords/services/garmin2influx-env.age;
|
||||
owner = "charlotte";
|
||||
};
|
||||
};
|
||||
}
|
88
modules/nixos/services/garmin-scraper/garmin2influx.py
Normal file
88
modules/nixos/services/garmin-scraper/garmin2influx.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
import os
|
||||
import sys
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
from garminconnect import (
|
||||
Garmin,
|
||||
GarminConnectConnectionError,
|
||||
GarminConnectTooManyRequestsError,
|
||||
GarminConnectAuthenticationError,
|
||||
)
|
||||
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
||||
from influxdb_client.client.write_api import SYNCHRONOUS
|
||||
|
||||
email = os.getenv('EMAIL')
|
||||
password = os.getenv('PASSWORD')
|
||||
token = os.getenv('TOKEN')
|
||||
org = 'default'
|
||||
bucket = 'default'
|
||||
|
||||
|
||||
def hr2point(time, val):
|
||||
return Point("health") \
|
||||
.field("heart_rate", val) \
|
||||
.time(
|
||||
datetime.fromtimestamp(time / 1000, timezone.utc),
|
||||
WritePrecision.S
|
||||
)
|
||||
|
||||
|
||||
def stress2point(time, val):
|
||||
return Point("health") \
|
||||
.field("stress", max(val, 0)) \
|
||||
.time(
|
||||
datetime.fromtimestamp(time / 1000, timezone.utc),
|
||||
WritePrecision.S
|
||||
)
|
||||
|
||||
|
||||
def hr_for_date(api, date_to_fetch):
|
||||
return api.get_heart_rates(date_to_fetch.isoformat())['heartRateValues']
|
||||
|
||||
|
||||
def stress_for_date(api, date_to_fetch):
|
||||
return api.get_stress_data(date_to_fetch.isoformat())['stressValuesArray']
|
||||
|
||||
|
||||
date_to_fetch = date.today().isoformat()
|
||||
if len(sys.argv) > 1:
|
||||
date_to_fetch = sys.argv[1]
|
||||
|
||||
date_to_fetch = date.fromisoformat(date_to_fetch)
|
||||
|
||||
try:
|
||||
api = Garmin(email, password)
|
||||
api.login()
|
||||
hr_points = list(map(
|
||||
lambda p: hr2point(*p),
|
||||
hr_for_date(api, date_to_fetch - timedelta(days=1))
|
||||
))
|
||||
stress_points = list(map(
|
||||
lambda p: stress2point(*p),
|
||||
stress_for_date(api, date_to_fetch - timedelta(days=1))
|
||||
))
|
||||
hr_points += list(map(
|
||||
lambda p: hr2point(*p),
|
||||
hr_for_date(api, date_to_fetch)
|
||||
))
|
||||
stress_points += list(map(
|
||||
lambda p: stress2point(*p),
|
||||
stress_for_date(api, date_to_fetch)
|
||||
))
|
||||
with InfluxDBClient(
|
||||
url="https://stats.chvp.be:8086",
|
||||
token=token,
|
||||
org=org
|
||||
) as client:
|
||||
write_api = client.write_api(write_options=SYNCHRONOUS)
|
||||
write_api.write(bucket, org, hr_points)
|
||||
write_api.write(bucket, org, stress_points)
|
||||
except (
|
||||
GarminConnectConnectionError,
|
||||
GarminConnectAuthenticationError,
|
||||
GarminConnectTooManyRequestsError,
|
||||
) as err:
|
||||
print(
|
||||
f'Error occured during Garmin Connect communication: {err}',
|
||||
file=sys.stderr
|
||||
)
|
||||
sys.exit(1)
|
85
modules/nixos/services/git/default.nix
Normal file
85
modules/nixos/services/git/default.nix
Normal file
|
@ -0,0 +1,85 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./runner.nix ];
|
||||
|
||||
options.chvp.services.git.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.git.enable {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "git.chvp.be";
|
||||
options = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
|
||||
extraConfig = ''
|
||||
client_max_body_size 50M;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}];
|
||||
users = {
|
||||
users = {
|
||||
git = {
|
||||
uid = lib.mkForce 963;
|
||||
group = "git";
|
||||
isSystemUser = true;
|
||||
useDefaultShell = true;
|
||||
};
|
||||
nginx.extraGroups = [ "git" ];
|
||||
};
|
||||
groups.git.gid = lib.mkForce 963;
|
||||
};
|
||||
services.openssh.settings.AcceptEnv = "GIT_PROTOCOL";
|
||||
services.gitlab = {
|
||||
enable = true;
|
||||
statePath = "/var/lib/git/state";
|
||||
backup.path = "/var/lib/git/backup";
|
||||
databaseCreateLocally = true;
|
||||
databaseUsername = "git";
|
||||
databaseName = "git";
|
||||
user = "git";
|
||||
group = "git";
|
||||
host = "git.chvp.be";
|
||||
port = 443;
|
||||
https = true;
|
||||
initialRootEmail = "charlotte@vanpetegem.be";
|
||||
initialRootPasswordFile = config.age.secrets."passwords/services/git/initial-root-password".path;
|
||||
# Hack, https://github.com/NixOS/nixpkgs/pull/135926 broke stuff
|
||||
pages.settings.pages-domain = "not.actually.enabled";
|
||||
secrets = {
|
||||
dbFile = config.age.secrets."passwords/services/git/db".path;
|
||||
jwsFile = config.age.secrets."passwords/services/git/jws".path;
|
||||
otpFile = config.age.secrets."passwords/services/git/otp".path;
|
||||
secretFile = config.age.secrets."passwords/services/git/secret".path;
|
||||
};
|
||||
smtp = {
|
||||
enable = true;
|
||||
enableStartTLSAuto = false;
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."passwords/services/git/initial-root-password" = {
|
||||
file = ../../../../secrets/passwords/services/git/initial-root-password.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/db" = {
|
||||
file = ../../../../secrets/passwords/services/git/db.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/jws" = {
|
||||
file = ../../../../secrets/passwords/services/git/jws.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/otp" = {
|
||||
file = ../../../../secrets/passwords/services/git/otp.age;
|
||||
owner = "git";
|
||||
};
|
||||
age.secrets."passwords/services/git/secret" = {
|
||||
file = ../../../../secrets/passwords/services/git/secret.age;
|
||||
owner = "git";
|
||||
};
|
||||
};
|
||||
}
|
57
modules/nixos/services/git/runner.nix
Normal file
57
modules/nixos/services/git/runner.nix
Normal file
|
@ -0,0 +1,57 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.git.runner.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.git.runner.enable {
|
||||
services.gitlab-runner = {
|
||||
enable = true;
|
||||
settings.concurrent = 8;
|
||||
services = {
|
||||
nix = {
|
||||
authenticationTokenConfigFile = config.age.secrets."passwords/services/gitlab-runner/registration".path;
|
||||
dockerImage = "alpine";
|
||||
dockerVolumes = [
|
||||
"/nix/store:/nix/store:ro"
|
||||
"/nix/var/nix/db:/nix/var/nix/db:ro"
|
||||
"/nix/var/nix/daemon-socket:/nix/var/nix/daemon-socket:ro"
|
||||
"/etc/nix/nix.conf:/etc/nix/nix.conf:ro"
|
||||
];
|
||||
preBuildScript = pkgs.writeScript "setup-container" ''
|
||||
mkdir -p -m 0755 /nix/var/log/nix/drvs
|
||||
mkdir -p -m 0755 /nix/var/nix/gcroots
|
||||
mkdir -p -m 0755 /nix/var/nix/profiles
|
||||
mkdir -p -m 0755 /nix/var/nix/temproots
|
||||
mkdir -p -m 0755 /nix/var/nix/userpool
|
||||
mkdir -p -m 1777 /nix/var/nix/gcroots/per-user
|
||||
mkdir -p -m 1777 /nix/var/nix/profiles/per-user
|
||||
mkdir -p -m 0755 /nix/var/nix/profiles/per-user/root
|
||||
mkdir -p -m 0700 "$HOME/.nix-defexpr"
|
||||
|
||||
. ${pkgs.nix}/etc/profile.d/nix.sh
|
||||
|
||||
${pkgs.nix}/bin/nix-env -i ${lib.concatStringsSep " " (with pkgs; [ nix cacert git openssh ])}
|
||||
'';
|
||||
environmentVariables = {
|
||||
ENV = "/etc/profile";
|
||||
USER = "root";
|
||||
NIX_REMOTE = "daemon";
|
||||
PATH = "/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
NIX_SSL_CERT_FILE = "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt";
|
||||
};
|
||||
requestConcurrency = 4;
|
||||
};
|
||||
};
|
||||
};
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
storageDriver = "zfs";
|
||||
};
|
||||
age.secrets."passwords/services/gitlab-runner/registration" = {
|
||||
file = ../../../../secrets/passwords/services/gitlab-runner/registration.age;
|
||||
};
|
||||
};
|
||||
}
|
97
modules/nixos/services/grafana/default.nix
Normal file
97
modules/nixos/services/grafana/default.nix
Normal file
|
@ -0,0 +1,97 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.grafana.enable = lib.mkEnableOption "grafana";
|
||||
|
||||
config = lib.mkIf config.chvp.services.grafana.enable {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "stats.chvp.be";
|
||||
options.locations."/" = {
|
||||
proxyPass = "http://grafana";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
}];
|
||||
users.users = {
|
||||
influxdb2.extraGroups = [ "acme" ];
|
||||
nginx.extraGroups = [ "grafana" ];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 8086 ];
|
||||
services = {
|
||||
nginx.upstreams.grafana.servers = { "unix:/run/grafana/grafana.sock" = { }; };
|
||||
influxdb2 = {
|
||||
enable = true;
|
||||
settings = {
|
||||
reporting-disabled = true;
|
||||
tls-cert = "${config.security.acme.certs."vanpetegem.me".directory}/fullchain.pem";
|
||||
tls-key = "${config.security.acme.certs."vanpetegem.me".directory}/key.pem";
|
||||
};
|
||||
};
|
||||
grafana = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/grafana";
|
||||
settings = {
|
||||
analytics.reporting_enabled = false;
|
||||
"auth.anonymous" = {
|
||||
enabled = "true";
|
||||
org_name = "Van Petegem";
|
||||
};
|
||||
database = {
|
||||
user = "grafana";
|
||||
type = "postgres";
|
||||
host = "/run/postgresql/";
|
||||
name = "grafana";
|
||||
};
|
||||
security = {
|
||||
admin_user = "chvp";
|
||||
admin_password = "$__file{${config.age.secrets."passwords/services/grafana/admin-password".path}}";
|
||||
secret_key = "$__file{${config.age.secrets."passwords/services/grafana/secret-key".path}}";
|
||||
};
|
||||
server = {
|
||||
domain = "stats.chvp.be";
|
||||
http_port = 3000;
|
||||
protocol = "socket";
|
||||
root_url = "https://stats.chvp.be";
|
||||
socket = "/run/grafana/grafana.sock";
|
||||
};
|
||||
smtp = {
|
||||
enabled = true;
|
||||
host = "mail.vanpetegem.me:25";
|
||||
user = "noreply@vanpetegem.me";
|
||||
from_address = "noreply@vanpetegem.me";
|
||||
password = "$__file{${config.age.secrets."passwords/services/grafana/smtp".path}}";
|
||||
};
|
||||
users = {
|
||||
default_theme = "light";
|
||||
allow_sign_up = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
grafana-image-renderer = {
|
||||
enable = true;
|
||||
provisionGrafana = true;
|
||||
chromium = pkgs.ungoogled-chromium;
|
||||
};
|
||||
postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
ensureDatabases = [ "grafana" ];
|
||||
ensureUsers = [{
|
||||
name = "grafana";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
};
|
||||
age.secrets."passwords/services/grafana/smtp" = {
|
||||
file = ../../../../secrets/passwords/services/grafana/smtp.age;
|
||||
owner = "grafana";
|
||||
};
|
||||
age.secrets."passwords/services/grafana/admin-password" = {
|
||||
file = ../../../../secrets/passwords/services/grafana/admin-password.age;
|
||||
owner = "grafana";
|
||||
};
|
||||
age.secrets."passwords/services/grafana/secret-key" = {
|
||||
file = ../../../../secrets/passwords/services/grafana/secret-key.age;
|
||||
owner = "grafana";
|
||||
};
|
||||
};
|
||||
}
|
166
modules/nixos/services/mail/default.nix
Normal file
166
modules/nixos/services/mail/default.nix
Normal file
|
@ -0,0 +1,166 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
keyFile = "${config.security.acme.certs."vanpetegem.me".directory}/key.pem";
|
||||
certFile = "${config.security.acme.certs."vanpetegem.me".directory}/fullchain.pem";
|
||||
in
|
||||
{
|
||||
options.chvp.services.mail.enable = lib.mkEnableOption "mail";
|
||||
|
||||
config = lib.mkIf config.chvp.services.mail.enable {
|
||||
chvp.base.zfs.systemLinks = [
|
||||
{ path = "/var/lib/dhparams"; type = "cache"; }
|
||||
{ path = "/var/lib/dovecot"; type = "cache"; }
|
||||
{ path = "/var/lib/opendkim"; type = "cache"; }
|
||||
{ path = "/var/lib/postfix"; type = "cache"; }
|
||||
{ path = "/var/lib/redis-rspamd"; type = "cache"; }
|
||||
{ path = "/var/lib/rspamd"; type = "cache"; }
|
||||
{ path = "/var/sieve"; type = "data"; }
|
||||
];
|
||||
mailserver = {
|
||||
enable = true;
|
||||
enableManageSieve = true;
|
||||
fqdn = "mail.vanpetegem.me";
|
||||
domains = [
|
||||
"accentor.tech"
|
||||
"chvp.be"
|
||||
"cvpetegem.be"
|
||||
"robbe.be"
|
||||
"robbevanpetegem.be"
|
||||
"robbevp.be"
|
||||
"toekomstlabo.be"
|
||||
"vanpetegem.be"
|
||||
"vanpetegem.me"
|
||||
];
|
||||
localDnsResolver = false;
|
||||
loginAccounts = {
|
||||
"charlotte@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/charlotte@vanpetegem.be".path;
|
||||
aliases = [ "@chvp.be" "@cvpetegem.be" "charlotte@vanpetegem.me" ];
|
||||
};
|
||||
"huis@vanpetegem.me".hashedPasswordFile = config.age.secrets."passwords/services/mail/huis@vanpetegem.me".path;
|
||||
"noreply@vanpetegem.me" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/noreply@vanpetegem.me".path;
|
||||
sendOnly = true;
|
||||
};
|
||||
"peter@vanpetegem.me".hashedPasswordFile = config.age.secrets."passwords/services/mail/peter@vanpetegem.me".path;
|
||||
"postbot@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/postbot@vanpetegem.be".path;
|
||||
aliases = [ "@vanpetegem.me" "@vanpetegem.be" ];
|
||||
};
|
||||
"robbe@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/robbe@vanpetegem.be".path;
|
||||
aliases = [ "robbe.nb@vanpetegem.me" "robbe@vanpetegem.me" ];
|
||||
};
|
||||
"robbe@robbevanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/robbe@robbevanpetegem.be".path;
|
||||
aliases = [ "@robbevanpetegem.be" ];
|
||||
};
|
||||
"hallo@robbe.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/hallo@robbe.be".path;
|
||||
aliases = [ "@robbe.be" "@robbevp.be" ];
|
||||
};
|
||||
"webmaster@vanpetegem.be" = {
|
||||
hashedPasswordFile = config.age.secrets."passwords/services/mail/webmaster@vanpetegem.be".path;
|
||||
aliases = [ "webmaster@vanpetegem.me" ];
|
||||
};
|
||||
};
|
||||
indexDir = "${config.chvp.cachePrefix}/var/lib/dovecot/indices";
|
||||
fullTextSearch = {
|
||||
enable = false;
|
||||
memoryLimit = 4000;
|
||||
};
|
||||
lmtpSaveToDetailMailbox = "no";
|
||||
mailboxes = {
|
||||
Trash = {
|
||||
auto = "no";
|
||||
specialUse = "Trash";
|
||||
autoexpunge = "60d";
|
||||
};
|
||||
Junk = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Junk";
|
||||
autoexpunge = "60d";
|
||||
};
|
||||
Drafts = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Drafts";
|
||||
};
|
||||
Sent = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Sent";
|
||||
};
|
||||
};
|
||||
extraVirtualAliases = {
|
||||
"team@accentor.tech" = [ "charlotte@vanpetegem.be" "robbe@vanpetegem.be" ];
|
||||
};
|
||||
forwards = {
|
||||
"info@toekomstlabo.be" = "robbe+toekomstlabo@robbevanpetegem.be";
|
||||
};
|
||||
rejectRecipients = [
|
||||
"cindy@vanpetegem.be"
|
||||
"contact@vanpetegem.be"
|
||||
"info@vanpetegem.be"
|
||||
"isabelle@vanpetegem.be"
|
||||
"marierose@vanpetegem.be"
|
||||
"rudy@vanpetegem.be"
|
||||
"sarina@vanpetegem.be"
|
||||
"sabrina@vanpetegem.be"
|
||||
];
|
||||
rejectSender = [
|
||||
"junjunggaming07@gmail.com"
|
||||
"censysnetbackup@gmail.com"
|
||||
"vitor.carvalheiro@escola.pr.gov.br"
|
||||
"spam@vuztc.ru"
|
||||
"mofos@theportalnetworks.com" # Someone registered my f-droid contact address on a porn site :(
|
||||
];
|
||||
mailDirectory = "${config.chvp.dataPrefix}/var/vmail";
|
||||
useFsLayout = false;
|
||||
certificateScheme = "manual";
|
||||
certificateFile = certFile;
|
||||
keyFile = keyFile;
|
||||
dkimKeyDirectory = "${config.chvp.dataPrefix}/var/dkim";
|
||||
};
|
||||
|
||||
services.dovecot2.sieve = {
|
||||
extensions = [ "editheader" ];
|
||||
scripts.after2 = pkgs.writeText "custom-spam.sieve" ''
|
||||
require ["fileinto", "regex"];
|
||||
|
||||
if anyof(
|
||||
# Freshdesk is often used to sent spam from emails like `support@info5813.freshdesk.com`
|
||||
address :regex "From" "[a-z\d]+@[a-z\d]+\.freshdesk\.com",
|
||||
header :contains "From" ["jakubbielec", "Jakub Bielec"],
|
||||
# Stop any mail pretending to be from itsme not from their official domains
|
||||
allof(
|
||||
address :contains "From" "itsme",
|
||||
not address :matches :domain "from" ["*itsme.be", "*itsme-id.com"]
|
||||
)
|
||||
) {
|
||||
fileinto "Junk";
|
||||
stop;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
services.rspamd.extraConfig = ''
|
||||
actions {
|
||||
reject = null;
|
||||
add_header = 6;
|
||||
greylist = 4;
|
||||
}
|
||||
'';
|
||||
|
||||
age.secrets = {
|
||||
"passwords/services/mail/charlotte@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/charlotte_at_vanpetegem.be.age;
|
||||
"passwords/services/mail/hallo@robbe.be".file = ../../../../secrets/passwords/services/mail/hallo_at_robbe.be.age;
|
||||
"passwords/services/mail/huis@vanpetegem.me".file = ../../../../secrets/passwords/services/mail/huis_at_vanpetegem.me.age;
|
||||
"passwords/services/mail/noreply@vanpetegem.me".file = ../../../../secrets/passwords/services/mail/noreply_at_vanpetegem.me.age;
|
||||
"passwords/services/mail/peter@vanpetegem.me".file = ../../../../secrets/passwords/services/mail/peter_at_vanpetegem.me.age;
|
||||
"passwords/services/mail/postbot@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/postbot_at_vanpetegem.be.age;
|
||||
"passwords/services/mail/robbe@robbevanpetegem.be".file = ../../../../secrets/passwords/services/mail/robbe_at_robbevanpetegem.be.age;
|
||||
"passwords/services/mail/robbe@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/robbe_at_vanpetegem.be.age;
|
||||
"passwords/services/mail/webmaster@vanpetegem.be".file = ../../../../secrets/passwords/services/mail/webmaster_at_vanpetegem.be.age;
|
||||
};
|
||||
};
|
||||
}
|
75
modules/nixos/services/mastodon/default.nix
Normal file
75
modules/nixos/services/mastodon/default.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.mastodon.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.mastodon.enable {
|
||||
chvp.services.nginx.hosts = [{
|
||||
fqdn = "social.chvp.be";
|
||||
options = {
|
||||
root = "${pkgs.mastodon}/public/";
|
||||
locations = {
|
||||
"/system/".alias = "/var/lib/mastodon/public-system/";
|
||||
"/".tryFiles = "$uri @proxy";
|
||||
"@proxy" = {
|
||||
proxyPass = "http://unix:/run/mastodon-web/web.socket";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
"/api/v1/streaming" = {
|
||||
proxyPass = "http://unix:/run/mastodon-streaming/streaming.socket";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}];
|
||||
users = {
|
||||
users = {
|
||||
mastodon.uid = 989;
|
||||
nginx.extraGroups = [ "mastodon" ];
|
||||
};
|
||||
groups.mastodon.gid = 985;
|
||||
};
|
||||
services.mastodon = {
|
||||
enable = true;
|
||||
configureNginx = false;
|
||||
localDomain = "social.chvp.be";
|
||||
enableUnixSocket = true;
|
||||
streamingProcesses = 4;
|
||||
|
||||
database.createLocally = true;
|
||||
redis.createLocally = true;
|
||||
smtp = {
|
||||
fromAddress = "social@chvp.be";
|
||||
createLocally = false;
|
||||
};
|
||||
extraConfig = {
|
||||
SMTP_OPENSSL_VERIFY_MODE = "none";
|
||||
};
|
||||
|
||||
otpSecretFile = config.age.secrets."passwords/services/mastodon/otp".path;
|
||||
secretKeyBaseFile = config.age.secrets."passwords/services/mastodon/key".path;
|
||||
vapidPublicKeyFile = config.age.secrets."passwords/services/mastodon/vapid-public".path;
|
||||
vapidPrivateKeyFile = config.age.secrets."passwords/services/mastodon/vapid-private".path;
|
||||
};
|
||||
|
||||
age.secrets."passwords/services/mastodon/vapid-public" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/vapid-public.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
age.secrets."passwords/services/mastodon/vapid-private" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/vapid-private.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
age.secrets."passwords/services/mastodon/key" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/key.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
age.secrets."passwords/services/mastodon/otp" = {
|
||||
file = ../../../../secrets/passwords/services/mastodon/otp.age;
|
||||
owner = "mastodon";
|
||||
};
|
||||
};
|
||||
}
|
229
modules/nixos/services/matrix/default.nix
Normal file
229
modules/nixos/services/matrix/default.nix
Normal file
|
@ -0,0 +1,229 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.matrix.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.matrix.enable {
|
||||
chvp.base.zfs.systemLinks = [{ path = "/var/lib/matrix-hookshot"; type = "data"; }];
|
||||
chvp.services.nginx.hosts = [
|
||||
{
|
||||
fqdn = "matrix.vanpetegem.me";
|
||||
options.locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://127.0.0.1:8448";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_read_timeout 600;
|
||||
client_max_body_size 10M;
|
||||
'';
|
||||
};
|
||||
"/_slack" = {
|
||||
proxyPass = "http://127.0.0.1:9898";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
'';
|
||||
};
|
||||
"~ ^/_hookshot/(.*)" = {
|
||||
proxyPass = "http://127.0.0.1:9000/$1";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
fqdn = "matrix-sync.vanpetegem.me";
|
||||
basicProxy = "http://localhost:8009";
|
||||
}
|
||||
];
|
||||
|
||||
services = {
|
||||
matrix-synapse = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server_name = "vanpetegem.me";
|
||||
public_baseurl = "https://matrix.vanpetegem.me";
|
||||
listeners = [{
|
||||
port = 8448;
|
||||
bind_addresses = [ "::1" "127.0.0.1" ];
|
||||
type = "http";
|
||||
tls = false;
|
||||
x_forwarded = true;
|
||||
resources = [
|
||||
{ names = [ "client" ]; compress = true; }
|
||||
{ names = [ "federation" ]; compress = false; }
|
||||
];
|
||||
}];
|
||||
url_preview_enabled = true;
|
||||
enable_metrics = false;
|
||||
enable_registration = false;
|
||||
report_stats = false;
|
||||
allow_guest_access = false;
|
||||
suppress_key_server_warning = true;
|
||||
app_service_config_files = [
|
||||
config.age.secrets."files/services/matrix-synapse/whatsapp-registration.yml".path
|
||||
config.age.secrets."files/services/matrix-synapse/slack-registration.yml".path
|
||||
config.age.secrets."files/services/matrix-synapse/hookshot-registration.yml".path
|
||||
];
|
||||
};
|
||||
extraConfigFiles = [
|
||||
config.age.secrets."files/services/matrix-synapse/config.yml".path
|
||||
];
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/matrix-synapse";
|
||||
};
|
||||
postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
ensureDatabases = [
|
||||
"matrix-synapse"
|
||||
"matrix_appservice_slack"
|
||||
"mautrix_whatsapp"
|
||||
];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "matrix_appservice_slack";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "mautrix_whatsapp";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "matrix-synapse";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
matrix-sliding-sync = {
|
||||
enable = true;
|
||||
settings = {
|
||||
SYNCV3_SERVER = "https://matrix.vanpetegem.me";
|
||||
};
|
||||
environmentFile = config.age.secrets."files/servers/matrix-sliding-sync/env".path;
|
||||
createDatabase = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
matrix-appservice-slack = {
|
||||
description = "Matrix <-> Slack bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "postgresql.service" "matrix-synapse.service" ];
|
||||
requires = [ "postgresql.service" "matrix-synapse.service" ];
|
||||
script = "${pkgs.matrix-appservice-slack}/bin/matrix-appservice-slack --config ${config.age.secrets."files/services/matrix-appservice-slack/config.yml".path} --file ${config.age.secrets."files/services/matrix-appservice-slack/registration.yml".path}";
|
||||
serviceConfig = {
|
||||
User = "matrix_appservice_slack";
|
||||
Group = "matrix_appservice_slack";
|
||||
};
|
||||
};
|
||||
matrix-synapse = {
|
||||
requires = [ "postgresql.service" ];
|
||||
};
|
||||
mautrix-whatsapp = {
|
||||
description = "Matrix <-> WhatsApp bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "postgresql.service" "matrix-synapse.service" ];
|
||||
requires = [ "postgresql.service" "matrix-synapse.service" ];
|
||||
script = "${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp --config ${config.age.secrets."files/services/mautrix-whatsapp/config.yml".path}";
|
||||
serviceConfig = {
|
||||
User = "mautrix_whatsapp";
|
||||
Group = "mautrix_whatsapp";
|
||||
};
|
||||
};
|
||||
matrix-hookshot = {
|
||||
description = "Matrix <-> Services bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "matrix-synapse.service" ];
|
||||
requires = [ "matrix-synapse.service" ];
|
||||
script = "${pkgs.matrix-hookshot}/bin/matrix-hookshot ${config.age.secrets."files/services/matrix-hookshot/config.yml".path} ${config.age.secrets."files/services/matrix-hookshot/registration.yml".path}";
|
||||
serviceConfig = {
|
||||
User = "matrix_hookshot";
|
||||
Group = "matrix_hookshot";
|
||||
WorkingDirectory = "/var/lib/matrix-hookshot";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users = {
|
||||
users = {
|
||||
matrix_appservice_slack = {
|
||||
uid = 998;
|
||||
group = "matrix_appservice_slack";
|
||||
isSystemUser = true;
|
||||
};
|
||||
mautrix_whatsapp = {
|
||||
uid = 997;
|
||||
group = "mautrix_whatsapp";
|
||||
isSystemUser = true;
|
||||
};
|
||||
matrix_hookshot = {
|
||||
uid = 979;
|
||||
group = "matrix_hookshot";
|
||||
home = "/var/lib/matrix-hookshot";
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
groups = {
|
||||
matrix_appservice_slack = {
|
||||
gid = 998;
|
||||
};
|
||||
mautrix_whatsapp = {
|
||||
gid = 997;
|
||||
};
|
||||
matrix_hookshot = {
|
||||
gid = 979;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."files/services/matrix-appservice-slack/config.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-appservice-slack/config.yml.age;
|
||||
owner = "matrix_appservice_slack";
|
||||
};
|
||||
age.secrets."files/services/matrix-appservice-slack/registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-appservice-slack/registration.yml.age;
|
||||
owner = "matrix_appservice_slack";
|
||||
};
|
||||
age.secrets."files/services/matrix-hookshot/config.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/config.yml.age;
|
||||
owner = "matrix_hookshot";
|
||||
};
|
||||
age.secrets."files/services/matrix-hookshot/registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/registration.yml.age;
|
||||
owner = "matrix_hookshot";
|
||||
};
|
||||
age.secrets."files/services/matrix-hookshot/passkey.pem" = {
|
||||
path = "/var/lib/matrix-hookshot/passkey.pem";
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/passkey.pem.age;
|
||||
owner = "matrix_hookshot";
|
||||
};
|
||||
age.secrets."files/services/mautrix-whatsapp/config.yml" = {
|
||||
file = ../../../../secrets/files/services/mautrix-whatsapp/config.yml.age;
|
||||
owner = "mautrix_whatsapp";
|
||||
};
|
||||
age.secrets."files/services/mautrix-whatsapp/registration.yml" = {
|
||||
file = ../../../../secrets/files/services/mautrix-whatsapp/registration.yml.age;
|
||||
owner = "mautrix_whatsapp";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/config.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-synapse/config.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/slack-registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-appservice-slack/registration.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/whatsapp-registration.yml" = {
|
||||
file = ../../../../secrets/files/services/mautrix-whatsapp/registration.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/services/matrix-synapse/hookshot-registration.yml" = {
|
||||
file = ../../../../secrets/files/services/matrix-hookshot/registration.yml.age;
|
||||
owner = "matrix-synapse";
|
||||
};
|
||||
age.secrets."files/servers/matrix-sliding-sync/env".file = ../../../../secrets/files/services/matrix-sliding-sync/env.age;
|
||||
};
|
||||
}
|
68
modules/nixos/services/nextcloud/default.nix
Normal file
68
modules/nixos/services/nextcloud/default.nix
Normal file
|
@ -0,0 +1,68 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.nextcloud.enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
config = lib.mkIf config.chvp.services.nextcloud.enable {
|
||||
services = {
|
||||
nextcloud = {
|
||||
home = "${config.chvp.dataPrefix}/var/lib/nextcloud";
|
||||
https = true;
|
||||
hostName = "nextcloud.vanpetegem.me";
|
||||
enable = true;
|
||||
autoUpdateApps.enable = true;
|
||||
package = pkgs.nextcloud29;
|
||||
caching.redis = true;
|
||||
config = {
|
||||
dbuser = "nextcloud";
|
||||
dbname = "nextcloud";
|
||||
dbtype = "pgsql";
|
||||
dbhost = "/run/postgresql";
|
||||
adminuser = "admin";
|
||||
adminpassFile = config.age.secrets."passwords/services/nextcloud-admin".path;
|
||||
};
|
||||
settings.redis = {
|
||||
host = "127.0.0.1";
|
||||
port = 31638;
|
||||
dbindex = 0;
|
||||
timeout = 1.5;
|
||||
};
|
||||
};
|
||||
nginx.virtualHosts."nextcloud.vanpetegem.me" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "vanpetegem.me";
|
||||
extraConfig = ''
|
||||
fastcgi_connect_timeout 10m;
|
||||
fastcgi_read_timeout 10m;
|
||||
fastcgi_send_timeout 10m;
|
||||
'';
|
||||
};
|
||||
postgresql = {
|
||||
enable = true;
|
||||
dataDir = "${config.chvp.dataPrefix}/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
ensureDatabases = [ "nextcloud" ];
|
||||
ensureUsers = [{
|
||||
name = "nextcloud";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
redis.servers.nextcloud = {
|
||||
enable = true;
|
||||
port = 31638;
|
||||
bind = "127.0.0.1";
|
||||
};
|
||||
};
|
||||
age.secrets."passwords/services/nextcloud-admin" = {
|
||||
file = ../../../../secrets/passwords/services/nextcloud-admin.age;
|
||||
owner = "nextcloud";
|
||||
};
|
||||
systemd.services."nextcloud-setup" = {
|
||||
requires = [ "postgresql.service" ];
|
||||
after = [ "postgresql.service" ];
|
||||
};
|
||||
users.users.nextcloud.uid = 996;
|
||||
users.groups.nextcloud.gid = 996;
|
||||
};
|
||||
}
|
88
modules/nixos/services/nginx/default.nix
Normal file
88
modules/nixos/services/nginx/default.nix
Normal file
|
@ -0,0 +1,88 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.nginx = {
|
||||
enable = lib.mkOption {
|
||||
readOnly = true;
|
||||
default = (builtins.length config.chvp.services.nginx.hosts) > 0;
|
||||
};
|
||||
hosts = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [
|
||||
{
|
||||
fqdn = "data.vanpetegem.me";
|
||||
options = {
|
||||
default = true;
|
||||
root = "/srv/data";
|
||||
locations = {
|
||||
"/".extraConfig = ''
|
||||
autoindex on;
|
||||
'';
|
||||
"/public".extraConfig = ''
|
||||
autoindex on;
|
||||
auth_basic off;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.nginx.enable {
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
security.acme = {
|
||||
certs."vanpetegem.me" = {
|
||||
dnsProvider = "cloudflare";
|
||||
credentialsFile = config.age.secrets."passwords/services/acme".path;
|
||||
extraDomainNames = [
|
||||
"*.vanpetegem.me"
|
||||
"cvpetegem.be"
|
||||
"*.cvpetegem.be"
|
||||
"chvp.be"
|
||||
"*.chvp.be"
|
||||
"vanpetegem.be"
|
||||
"*.vanpetegem.be"
|
||||
];
|
||||
};
|
||||
defaults.email = "webmaster@vanpetegem.me";
|
||||
acceptTerms = true;
|
||||
preliminarySelfsigned = false;
|
||||
};
|
||||
age.secrets."passwords/services/acme" = {
|
||||
file = ../../../../secrets/passwords/services/acme.age;
|
||||
owner = "acme";
|
||||
};
|
||||
chvp.base.zfs.systemLinks = [
|
||||
{ type = "data"; path = "/var/lib/acme"; }
|
||||
];
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts = builtins.listToAttrs
|
||||
(map
|
||||
(elem: {
|
||||
name = elem.fqdn;
|
||||
value = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "vanpetegem.me";
|
||||
locations."/" = lib.mkIf (builtins.hasAttr "basicProxy" elem) {
|
||||
proxyPass = elem.basicProxy;
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
'' + (elem.extraProxySettings or "");
|
||||
};
|
||||
} // (elem.options or { });
|
||||
})
|
||||
config.chvp.services.nginx.hosts);
|
||||
};
|
||||
users.users = {
|
||||
nginx.extraGroups = [ "acme" ];
|
||||
acme.uid = 999;
|
||||
};
|
||||
users.groups.acme.gid = 999;
|
||||
};
|
||||
}
|
41
modules/nixos/services/torrents/default.nix
Normal file
41
modules/nixos/services/torrents/default.nix
Normal file
|
@ -0,0 +1,41 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.chvp.services.torrents = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.chvp.services.torrents.enable {
|
||||
chvp.services.nginx.hosts = [{ fqdn = "transmission.vanpetegem.me"; basicProxy = "http://localhost:9091"; }];
|
||||
|
||||
services.transmission = {
|
||||
enable = true;
|
||||
package = pkgs.transmission_4;
|
||||
user = "charlotte";
|
||||
group = "users";
|
||||
home = "/data/var/lib/transmission";
|
||||
openRPCPort = false;
|
||||
openPeerPorts = true;
|
||||
credentialsFile = config.age.secrets."files/programs/transmission/config.json".path;
|
||||
settings = {
|
||||
umask = 18;
|
||||
download-dir = "/srv/data";
|
||||
incomplete-dir = "/srv/data/.incomplete";
|
||||
rpc-authentication-required = true;
|
||||
rpc-bind-address = "0.0.0.0";
|
||||
rpc-enabled = true;
|
||||
rpc-host-whitelist-enabled = false;
|
||||
rpc-whitelist-enabled = false;
|
||||
speed-limit-down = 51200;
|
||||
speed-limit-down-enabled = true;
|
||||
};
|
||||
};
|
||||
age.secrets."files/programs/transmission/config.json" = {
|
||||
file = ../../../../secrets/files/programs/transmission/config.json.age;
|
||||
owner = "charlotte";
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue