In a pretty good working state

This commit is contained in:
root 2020-02-03 19:07:46 -06:00
parent 00a97b1d94
commit 2aa6b8efc6
41 changed files with 1418 additions and 1155 deletions

220
config/fudo/chat.nix Normal file
View File

@ -0,0 +1,220 @@
{ pkgs, lib, config, ... }:
with lib;
let
cfg = config.fudo.chat;
in {
options.fudo.chat = {
enable = mkEnableOption "Enable chat server";
hostname = mkOption {
type = types.str;
description = "Hostname at which this chat server is accessible.";
example = "chat.mydomain.com";
};
site-name = mkOption {
type = types.str;
description = "The name of this chat server.";
example = "My Fancy Chat Site";
};
smtp-server = mkOption {
type = types.str;
description = "SMTP server to use for sending notification emails.";
example = "mail.my-site.com";
};
smtp-user = mkOption {
type = types.str;
description = "Username with which to connect to the SMTP server.";
};
smtp-password-file = mkOption {
type = types.path;
description = "Path to a file containing the password to use while connecting to the SMTP server.";
};
state-directory = mkOption {
type = types.str;
description = "Path at which to store server state data.";
default = "/var/lib/mattermost";
};
database = mkOption {
type = (types.submodule {
options = {
name = mkOption {
type = types.str;
description = "Database name.";
};
hostname = mkOption {
type = types.str;
description = "Database host.";
};
user = mkOption {
type = types.str;
description = "Database user.";
};
password-file = mkOption {
type = types.path;
description = "Path to file containing database password.";
};
};
});
description = "Database configuration.";
example = {
name = "my_database";
hostname = "my.database.com";
user = "db_user";
password-file = /path/to/some/file.pw;
};
};
};
config = mkIf cfg.enable (let
pkg = pkgs.mattermost;
default-config = builtins.fromJSON (readFile "${pkg}/config/config.json");
modified-config = recursiveUpdate default-config {
ServiceSettings.SiteURL = "https://${cfg.hostname}";
ServiceSettings.ListenAddress = "127.0.0.1:8065";
TeamSettings.SiteName = cfg.site-name;
EmailSettings = {
RequireEmailVerification = true;
SMTPServer = cfg.smtp-server;
SMTPPort = 587;
EnableSMTPAuth = true;
SMTPUsername = cfg.smtp-user;
SMTPPassword = (fileContents cfg.smtp-password-file);
SendEmailNotifications = true;
ConnectionSecurity = "STARTTLS";
FeedbackEmail = "chat@fudo.org";
FeedbackName = "Admin";
};
EnableEmailInvitations = true;
SqlSettings.DriverName = "postgres";
SqlSettings.DataSource =
"postgres://${cfg.database.user}:${fileContents cfg.database.password-file}@${cfg.database.hostname}:5432/${cfg.database.name}";
};
mattermost-config-file = pkgs.writeText "mattermost-config.json" (builtins.toJSON modified-config);
mattermost-user = "mattermost";
mattermost-group = "mattermost";
in {
users = {
users = {
${mattermost-user} = {
isSystemUser = true;
group = mattermost-group;
};
};
groups = {
${mattermost-group} = {
members = [ mattermost-user ];
};
};
};
system.activationScripts.mattermost = ''
mkdir -p ${cfg.state-directory}
'';
systemd.services.mattermost = {
description = "Mattermost Chat Server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
preStart = ''
mkdir -p ${cfg.state-directory}/config
cp ${mattermost-config-file} ${cfg.state-directory}/config/config.json
ln -sf ${pkg}/bin ${cfg.state-directory}
ln -sf ${pkg}/fonts ${cfg.state-directory}
ln -sf ${pkg}/i18n ${cfg.state-directory}
ln -sf ${pkg}/templates ${cfg.state-directory}
cp -uRL ${pkg}/client ${cfg.state-directory}
chown -R ${mattermost-user}:${mattermost-group} ${cfg.state-directory}
chmod u+w -R ${cfg.state-directory}/client
chmod o-rwx -R ${cfg.state-directory}
'';
serviceConfig = {
PermissionsStartOnly = true;
ExecStart = "${pkg}/bin/mattermost";
WorkingDirectory = cfg.state-directory;
Restart = "always";
RestartSec = "10";
LimitNOFILE = "49152";
User = mattermost-user;
Group = mattermost-group;
};
};
services.nginx = {
enable = true;
appendHttpConfig = ''
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=3g inactive=120m use_temp_path=off;
'';
virtualHosts = {
"${cfg.hostname}" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8065";
extraConfig = ''
client_max_body_size 50M;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
proxy_read_timeout 600s;
proxy_cache mattermost_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 2;
proxy_cache_use_stale timeout;
proxy_cache_lock on;
proxy_http_version 1.1;
'';
};
locations."~ /api/v[0-9]+/(users/)?websocket$" = {
proxyPass = "http://127.0.0.1:8065";
extraConfig = ''
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 50M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
client_body_timeout 60;
send_timeout 300;
lingering_timeout 5;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 90s;
'';
};
};
};
};
});
}

View File

@ -12,5 +12,39 @@ with lib;
''; '';
default = []; default = [];
}; };
domain = mkOption {
type = types.str;
description = ''
Domain of the
'';
};
profile = mkOption {
type = with types; nullOr str;
example = "desktop";
description = ''
The profile to use for this host. This will do some profile-dependent
configuration, for example removing X-libs from servers and adding UI
packages to desktops.
'';
default = null;
};
site = mkOption {
type = with types; nullOr str;
example = "seattle";
description = ''
The site at which this host is located. This will do some site-dependent
configuration.
'';
default = null;
};
www-root = mkOption {
type = types.path;
description = "Path at which to store www files for serving.";
example = /var/www;
};
}; };
} }

View File

@ -9,6 +9,27 @@ let
database-name = "grafana"; database-name = "grafana";
database-user = "grafana"; database-user = "grafana";
databaseOpts = { ... }: {
options = {
name = mkOption {
type = types.str;
description = "Database name.";
};
hostname = mkOption {
type = types.str;
description = "Hostname of the database server.";
};
user = mkOption {
type = types.str;
description = "Database username.";
};
password-file = mkOption {
type = types.path;
description = "File containing the database user's password.";
};
};
};
in { in {
options.fudo.grafana = { options.fudo.grafana = {
@ -30,9 +51,9 @@ in {
description = "Path to a file containing the email user's password."; description = "Path to a file containing the email user's password.";
}; };
database-password-file = mkOption { database = mkOption {
type = types.path; type = (types.submodule databaseOpts);
description = "Path to a file containing the database user's password."; description = "Grafana database configuration.";
}; };
admin-password-file = mkOption { admin-password-file = mkOption {
@ -52,15 +73,6 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
fudo.postgresql = {
databases.${database-name} = {};
local-users.${database-user} = {
password = (fileContents cfg.database-password-file);
databases = ["${database-name}"];
};
};
services.nginx = { services.nginx = {
enable = true; enable = true;
@ -89,6 +101,7 @@ in {
addr = "127.0.0.1"; addr = "127.0.0.1";
protocol = "http"; protocol = "http";
port = 3000;
domain = "${cfg.hostname}"; domain = "${cfg.hostname}";
rootUrl = "https://${cfg.hostname}/"; rootUrl = "https://${cfg.hostname}/";
@ -106,10 +119,10 @@ in {
}; };
database = { database = {
host = "localhost"; host = cfg.database.hostname;
name = database-name; name = cfg.database.name;
user = database-user; user = cfg.database.user;
passwordFile = cfg.database-password-file; passwordFile = cfg.database.password-file;
type = "postgres"; type = "postgres";
}; };

View File

@ -0,0 +1,117 @@
lib: site: config: version:
with lib;
let
db-config = if (config.database != null) then
''
type = "${config.database.type}"
pdo_dsn = "${config.database.type}:host=${config.database.hostname};port=${toString config.database.port};dbname=${config.database.name}"
pdo_user = "${config.database.user}"
pdo_password = "${fileContents config.database.password-file}"
''
else "";
in ''
[webmail]
title = "${config.title}"
loading_description = "${config.title}"
favicon_url = "https://${site}/favicon.ico"
theme = "${config.theme}"
allow_themes = On
allow_user_background = Off
language = "en"
language_admin = "en"
allow_languages_on_settings = On
allow_additional_accounts = On
allow_additional_identities = On
messages_per_page = ${toString config.messages-per-page}
attachment_size_limit = ${toString config.max-upload-size}
[interface]
show_attachment_thumbnail = On
new_move_to_folder_button = On
[branding]
[contacts]
enable = On
allow_sync = On
sync_interval = 20
suggestions_limit = 10
${db-config}
[security]
csrf_protection = On
custom_server_signature = "RainLoop"
x_frame_options_header = ""
openpgp = On
admin_login = "admin"
admin_password = ""
allow_admin_panel = Off
allow_two_factor_auth = On
force_two_factor_auth = Off
hide_x_mailer_header = Off
admin_panel_host = ""
admin_panel_key = "admin"
content_security_policy = ""
core_install_access_domain = ""
[login]
default_domain = "${config.domain}"
allow_languages_on_login = On
determine_user_language = On
determine_user_domain = Off
welcome_page = Off
hide_submit_button = On
[plugins]
enable = Off
[defaults]
view_editor_type = "${config.edit-mode}"
view_layout = ${if (config.layout-mode == "bottom") then "2" else "1"}
contacts_autosave = On
mail_use_threads = ${if config.enable-threading then "On" else "Off"}
allow_draft_autosave = On
mail_reply_same_folder = Off
show_images = On
[logs]
enable = ${if config.debug then "On" else "Off"}
[debug]
enable = ${if config.debug then "On" else "Off"}
hide_passwords = On
filename = "log-{date:Y-m-d}.txt"
[social]
google_enable = Off
fb_enable = Off
twitter_enable = Off
dropbox_enable = Off
[cache]
enable = On
index = "v1"
fast_cache_driver = "files"
fast_cache_index = "v1"
http = On
http_expires = 3600
server_uids = On
[labs]
allow_mobile_version = ${if config.enable-mobile then "On" else "Off"}
check_new_password_strength = On
allow_gravatar = On
allow_prefetch = On
allow_smart_html_links = On
cache_system_data = On
date_from_headers = On
autocreate_system_folders = On
allow_ctrl_enter_on_compose = On
favicon_status = On
use_local_proxy_for_external_images = On
detect_image_exif_orientation = On
[version]
current = "${version}"
''

View File

@ -69,7 +69,9 @@ in {
acl_file = ${cfg.acl-file} acl_file = ${cfg.acl-file}
} }
addresses = ${stringJoin " " cfg.bind-addresses} addresses = ${stringJoin " " cfg.bind-addresses}
enable-http = true
# Binds to port 80!
enable-http = false
''; '';
}; };
}; };

View File

@ -16,7 +16,7 @@ let
container-mail-user = "mailer"; container-mail-user = "mailer";
container-mail-user-id = 542; container-mail-user-id = 542;
container-mail-group = "mailer"; container-mail-group = "mailer";
trusted-networks = config.fudo.prometheus.trusted-networks; trusted-networks = config.fudo.common.local-networks;
in rec { in rec {
options.fudo.mail-server.container = { options.fudo.mail-server.container = {
@ -80,11 +80,11 @@ in rec {
proxy-headers = '' proxy-headers = ''
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host; proxy_set_header Host $host;
'' '';
;
trusted-network-string = optionalString ((length trusted-networks) > 0) trusted-network-string = optionalString ((length trusted-networks) > 0)
(concatStringsSep "\n" (concatStringsSep "\n"
(map (network: "allow ${network};") trusted-networks)) + "\ndeny all;"; (map (network: "allow ${network};") trusted-networks)) + "\ndeny all;";
in { in {
"${cfg.hostname}" = { "${cfg.hostname}" = {
enableACME = true; enableACME = true;

View File

@ -51,13 +51,13 @@ let
# A list of domains for which we accept mail # A list of domains for which we accept mail
virtual-mailbox-map-file = builtins.toFile "virtual_mailbox_map" virtual-mailbox-map-file = builtins.toFile "virtual_mailbox_map"
(concatStringsSep "\n" (concatStringsSep "\n"
(map (domain: "@${domain} OK") cfg.local-domains)); (map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain])));
sender-login-map-file = let sender-login-map-file = let
escapeDot = (str: replaceStrings ["."] ["\\."] str); escapeDot = (str: replaceStrings ["."] ["\\."] str);
in builtins.toFile "sender_login_maps" in builtins.toFile "sender_login_maps"
(concatStringsSep "\n" (concatStringsSep "\n"
(map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") cfg.local-domains)); (map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain])));
mapped-file = name: "hash:/var/lib/postfix/conf/${name}"; mapped-file = name: "hash:/var/lib/postfix/conf/${name}";
@ -95,6 +95,9 @@ in {
services.prometheus.exporters.postfix = mkIf cfg.monitoring { services.prometheus.exporters.postfix = mkIf cfg.monitoring {
enable = true; enable = true;
systemd.enable = true; systemd.enable = true;
showqPath = "/var/lib/postfix/queue/public/showq";
user = config.services.postfix.user;
group = config.services.postfix.group;
}; };
services.postfix = { services.postfix = {
@ -103,7 +106,8 @@ in {
origin = cfg.domain; origin = cfg.domain;
hostname = cfg.hostname; hostname = cfg.hostname;
destination = ["localhost" "localhost.localdomain"] ++ destination = ["localhost" "localhost.localdomain"] ++
(map (domain: "localhost.${domain}") cfg.local-domains); (map (domain: "localhost.${domain}") cfg.local-domains) ++
cfg.local-domains;
enableHeaderChecks = true; enableHeaderChecks = true;
enableSmtp = true; enableSmtp = true;
@ -153,6 +157,10 @@ in {
smtpd_sasl_type = "dovecot"; smtpd_sasl_type = "dovecot";
smtpd_sasl_path = "/run/dovecot2/auth"; smtpd_sasl_path = "/run/dovecot2/auth";
smtpd_sasl_auth_enable = "yes"; smtpd_sasl_auth_enable = "yes";
smtpd_sasl_local_domain = "fudo.org";
smtpd_sasl_security_options = "noanonymous";
smtpd_sasl_tls_security_options = "noanonymous";
smtpd_sender_login_maps = (pcre-file "sender_login_map"); smtpd_sender_login_maps = (pcre-file "sender_login_map");
@ -184,6 +192,9 @@ in {
smtpd_sender_restrictions = [ smtpd_sender_restrictions = [
"check_sender_access ${mapped-file "reject_senders"}" "check_sender_access ${mapped-file "reject_senders"}"
"permit_mynetworks"
"permit_sasl_authenticated"
"reject_unknown_sender_domain"
]; ];
smtpd_recipient_restrictions = [ smtpd_recipient_restrictions = [
@ -200,6 +211,12 @@ in {
"reject_non_fqdn_recipient" "reject_non_fqdn_recipient"
]; ];
smtpd_helo_restrictions = [
"permit_mynetworks"
"reject_invalid_hostname"
"permit"
];
# Handled by submission # Handled by submission
smtpd_tls_security_level = "may"; smtpd_tls_security_level = "may";

View File

@ -39,7 +39,7 @@ in {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
location."/metrics/node" = { locations."/metrics/node" = {
extraConfig = '' extraConfig = ''
${concatStringsSep "\n" (map allow-network fudo-cfg.local-networks)} ${concatStringsSep "\n" (map allow-network fudo-cfg.local-networks)}
allow 127.0.0.0/16; allow 127.0.0.0/16;

View File

@ -8,14 +8,18 @@ let
userOpts = { username, ... }: { userOpts = { username, ... }: {
options = { options = {
password = mkOption { password = mkOption {
type = types.str; type = with types; nullOr str;
description = "The user's (plaintext) password."; description = "The user's (plaintext) password.";
default = null;
}; };
databases = mkOption { databases = mkOption {
type = with types; listOf str; type = with types; loaOf str;
description = "Databases to which this user has access."; description = "Map of databases to which this user has access, to the required perms.";
default = []; default = {};
example = {
my_database = "ALL PRIVILEGES";
};
}; };
}; };
}; };
@ -24,19 +28,16 @@ let
options = { options = {
users = mkOption { users = mkOption {
type = with types; listOf str; type = with types; listOf str;
description = "A list of users who should have access to this database."; description = "A list of users who should have full access to this database.";
default = []; default = [];
}; };
}; };
}; };
userDatabaseAccess = user: databases: userDatabaseAccess = user: databases:
listToAttrs (map (database-name: mapAttrs' (database: perms:
{ nameValuePair "DATABASE ${database}" perms)
name = "DATABASE ${database-name}"; databases;
value = "ALL PRIVILEGES";
})
databases);
stringJoin = joiner: els: stringJoin = joiner: els:
if (length els) == 0 then if (length els) == 0 then
@ -54,9 +55,9 @@ let
"ALTER USER ${username} ENCRYPTED PASSWORD '${attrs.password}';"; "ALTER USER ${username} ENCRYPTED PASSWORD '${attrs.password}';";
setPasswordsSql = users: setPasswordsSql = users:
stringJoin "\n" (stringJoin "\n"
(mapAttrsToList (username: attrs: setPasswordSql username attrs) (mapAttrsToList (username: attrs: setPasswordSql username attrs)
users); (filterAttrs (user: attrs: attrs.password != null) users))) + "\n";
makeLocalUserPasswordEntries = users: makeLocalUserPasswordEntries = users:
stringJoin "\n" stringJoin "\n"
@ -66,7 +67,7 @@ let
(map (db: '' (map (db: ''
host ${username} ${db} 127.0.0.1/16 md5 host ${username} ${db} 127.0.0.1/16 md5
host ${username} ${db} ::1/128 md5 host ${username} ${db} ::1/128 md5
'') attrs.databases)) '') (attrNames attrs.databases)))
users); users);
@ -99,7 +100,7 @@ in {
default = []; default = [];
}; };
local-users = mkOption { users = mkOption {
type = with types; loaOf (submodule userOpts); type = with types; loaOf (submodule userOpts);
description = "A map of users to user attributes."; description = "A map of users to user attributes.";
example = { example = {
@ -146,6 +147,13 @@ in {
group = "postgres"; group = "postgres";
source = cfg.keytab; source = cfg.keytab;
}; };
"postgresql/private/user-script.sql" = {
mode = "0400";
user = "postgres";
group = "postgres";
text = setPasswordsSql cfg.users;
};
}; };
}; };
@ -162,7 +170,7 @@ in {
#{ "DATABASE ${username}" = "ALL PRIVILEGES"; }; #{ "DATABASE ${username}" = "ALL PRIVILEGES"; };
(userDatabaseAccess username attrs.databases); (userDatabaseAccess username attrs.databases);
}) })
cfg.local-users; cfg.users;
extraConfig = extraConfig =
'' ''
@ -179,7 +187,7 @@ in {
'' ''
local all all ident local all all ident
${makeLocalUserPasswordEntries cfg.local-users} ${makeLocalUserPasswordEntries cfg.users}
# host-local # host-local
host all all 127.0.0.1/32 gss include_realm=0 krb_realm=FUDO.ORG host all all 127.0.0.1/32 gss include_realm=0 krb_realm=FUDO.ORG
@ -189,9 +197,13 @@ in {
${makeNetworksEntry cfg.local-networks} ${makeNetworksEntry cfg.local-networks}
''; '';
initialScript = pkgs.writeText "database-init.sql" '' # initialScript = pkgs.writeText "database-init.sql" ''
${setPasswordsSql cfg.local-users} # ${setPasswordsSql cfg.users}
''; # '';
}; };
systemd.services.postgresql.postStart = ''
${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${pkgs.postgresql}/bin/psql --port ${toString config.services.postgresql.port} -f /etc/postgresql/private/user-script.sql -d postgres
'';
}; };
} }

View File

@ -1,32 +0,0 @@
# Switch between different basic profiles
{ lib, config, pkgs, ... }:
with lib;
let
profile = config.fudo.profile;
profiles = {
desktop = ./profiles/desktop.nix {
pkgs = pkgs;
config = config;
};
server = ./profiles/server.nix {
pkgs = pkgs;
config = config;
};
};
in {
options.fudo.profile = {
type = types.enum (attrNames profiles);
example = "desktop";
description = ''
The profile to use for this host. This will do some profile-dependent
configuration, for example removing X-libs from servers and adding UI
packages to desktops.
'';
default = "server";
};
config = optionalAttrs (profiles ? profile) profiles.${profile};
}

View File

@ -1,151 +0,0 @@
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
cool-retro-term
chrome-gnome-shell
chromium
ffmpeg-full
firefox
gimp
glxinfo
gnome3.gnome-shell
gnome3.gnome-session
google-chrome
gtk2
gtk2-x11
gtk3
gtkimageview
i3lock
libfixposix
minecraft
mplayer
nomacs
openssl_1_1
redshift
rhythmbox
shotwell
spotify
sqlite
steam
system-config-printer
virtmanager
xorg.xev
xzgv
virtmanager-qt
];
# Splash screen
boot.plymouth.enable = true;
services.avahi = {
enable = true;
browseDomains = [config.fudo.domain;];
domainName = config.fudo.domain;
};
boot.tmpOnTmpfs = true;
services.xserver = {
enable = true;
layout = "us";
xkbVariant = "dvp";
xkbOptions = "ctrl:nocaps";
desktopManager.gnome3.enable = true;
desktopManager.default = "gnome3";
displayManager.gdm.enable = true;
windowManager.session = pkgs.lib.singleton {
name = "stumpwm";
start = ''
${pkgs.lispPackages.stumpwm}/bin/stumpwm &
waidPID=$!
'';
};
};
services.printing = {
enable = true;
};
services.gnome3 = {
evolution-data-server.enable = pkgs.lib.mkForce false;
gnome-user-share.enable = pkgs.lib.mkForce false;
};
services.dbus.socketActivated = true;
services.openssh.forwardX11 = true;
programs.ssh.forwardX11 = true;
sound.enable = true;
hardware.pulseaudio.enable = true;
fonts = {
enableCoreFonts = true;
enableFontDir = true;
enableGhostscriptFonts = false;
fontconfig.ultimate.enable = true;
fonts = with pkgs; [
cantarell_fonts
dejavu_fonts
dina-font
dosemu_fonts
fira-code
fira-code-symbols
freefont_ttf
liberation_ttf
mplus-outline-fonts
nerdfonts
noto-fonts
noto-fonts-cjk
noto-fonts-emoji
proggyfonts
terminus_font
ubuntu_font_family
ucsFonts
unifont
vistafonts
xlibs.fontadobe100dpi
xlibs.fontadobe75dpi
xlibs.fontadobeutopia100dpi
xlibs.fontadobeutopia75dpi
xlibs.fontadobeutopiatype1
xlibs.fontarabicmisc
xlibs.fontbh100dpi
xlibs.fontbh75dpi
xlibs.fontbhlucidatypewriter100dpi
xlibs.fontbhlucidatypewriter75dpi
xlibs.fontbhttf
xlibs.fontbhtype1
xlibs.fontbitstream100dpi
xlibs.fontbitstream75dpi
xlibs.fontbitstreamtype1
xlibs.fontcronyxcyrillic
xlibs.fontcursormisc
xlibs.fontdaewoomisc
xlibs.fontdecmisc
xlibs.fontibmtype1
xlibs.fontisasmisc
xlibs.fontjismisc
xlibs.fontmicromisc
xlibs.fontmisccyrillic
xlibs.fontmiscethiopic
xlibs.fontmiscmeltho
xlibs.fontmiscmisc
xlibs.fontmuttmisc
xlibs.fontschumachermisc
xlibs.fontscreencyrillic
xlibs.fontsonymisc
xlibs.fontsunmisc
xlibs.fontwinitzkicyrillic
xlibs.fontxfree86type1
];
};
}

View File

@ -1,27 +0,0 @@
{ pkgs, ... }:
{
environment = {
systemPackages = with pkgs; [
];
noXlibs = true;
};
security = {
hideProcessInformation = true;
};
boot.tmpOnTmpfs = true;
services.xserver.enable = false;
programs = {
gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
ssh.startAgent = true;
};
}

View File

@ -1,79 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
site = config.fudo.site;
hostname = config.networking.hostName;
winnipeg-networks = [
"208.81.1.128/28"
"208.81.3.112/28"
"192.168.11.1/24"
];
site-configs = {
global-config = {
};
winnipeg = global-config // {
time.timeZone = "America/Winnipeg";
fudo.common.local-networks = winnipeg-networks;
services.cron = {
mailto = "admin@fudo.org";
};
networking = {
domain = "fudo.org";
search = ["fudo.org"];
firewall.enable = false;
networkmanager.enable = pkgs.lib.mkForce false;
nameservers = [ "1.1.1.1" "208.81.7.14" "2606:4700:4700::1111" ];
};
security.acme.certs."${hostname}" = {
email = "admin@fudo.org";
plugins = [
"fullchain.pem"
"full.pem"
"key.pem"
"chain.pem"
"cert.pem"
];
};
fudo.node-exporter = {
enable = true;
hostname = hostname;
};
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
};
};
nutty-club = winnipeg // {
defaultGateway = "208.81.3.113";
};
};
in {
options.fudo.site = mkOption {
type = types.enum (attrNames site-configs);
example = "nutty-club";
description = ''
The site at which this host is located. This will do some site-dependent
configuration.
'';
default = "";
};
config = optionalAttrs (site-configs ? site) site-configs.${site};
}

318
config/fudo/webmail.nix Normal file
View File

@ -0,0 +1,318 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.fudo.webmail;
inherit (lib.strings) concatStringsSep;
webmail-user = "webmail-php";
webmail-group = "webmail-php";
base-data-path = "/var/rainloop";
fastcgi-conf = builtins.toFile "fastcgi.conf" ''
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
'';
site-packages = mapAttrs (site: site-cfg:
pkgs.rainloop-community.overrideAttrs (oldAttrs: {
# Not sure how to correctly specify this arg...
#dataPath = "${base-data-path}/${site}";
# Overwriting, to correctly create data dir
installPhase = ''
mkdir $out
cp -r rainloop/* $out
rm -rf $out/data
ln -s ${base-data-path}/${site} $out/data
ln -s ${site-cfg.favicon} $out/favicon.ico
'';
}))
cfg.sites;
siteOpts = { site-host, ... }: {
options = {
title = mkOption {
type = types.str;
description = "Webmail site title";
example = "My Webmail";
};
debug = mkOption {
type = types.bool;
description = "Turn debug logs on.";
default = false;
};
mail-server = mkOption {
type = types.str;
description = "Mail server from which to send & recieve email.";
default = "mail.fudo.org";
};
favicon = mkOption {
type = types.str;
description = "URL of the site favicon";
example = "https://www.somepage.com/fav.ico";
};
messages-per-page = mkOption {
type = types.int;
description = "Default number of messages to show per page";
default = 30;
};
max-upload-size = mkOption {
type = types.int;
description = "Size limit in MB for uploaded files";
default = 30;
};
theme = mkOption {
type = types.str;
description = "Default theme to use for this webmail site.";
default = "Default";
};
# Ideally, don't even allow admin logins, since they'll just add state that can be clobbered
# admin-password = mkOption {
# type = types.str;
# description = "Password to use for the admin user";
# };
domain = mkOption {
type = types.str;
description = "Domain for which the server acts as webmail server";
};
edit-mode = mkOption {
type = types.enum ["Plain" "Html" "PlainForced" "HtmlForced"];
description = "Default text editing mode for email";
default = "Html";
};
layout-mode = mkOption {
type = types.enum ["side" "bottom"];
description = "Layout mode to use for email preview.";
default = "side";
};
enable-threading = mkOption {
type = types.bool;
description = "Whether to enable threading for email.";
default = true;
};
enable-mobile = mkOption {
type = types.bool;
description = "Whether to enable a mobile site view.";
default = true;
};
database = mkOption {
type = with types; nullOr (submodule databaseOpts);
description = "Database configuration for storing contact data.";
example = {
name = "my_db";
host = "db.domain.com";
user = "my_user";
password-file = /path/to/some/file.pw;
};
default = null;
};
};
};
databaseOpts = { ... }: {
options = {
type = mkOption {
type = types.enum ["pgsql" "mysql"];
description = "Driver to use when connecting to the database.";
default = "pgsql";
};
hostname = mkOption {
type = types.str;
description = "Name of host running the database.";
example = "my-db.domain.com";
};
port = mkOption {
type = types.int;
description = "Port on which the database server is listening.";
default = 5432;
};
name = mkOption {
type = types.str;
description = "Name of the database containing contact info. <user> must have access.";
default = "rainloop_contacts";
};
user = mkOption {
type = types.str;
description = "User as which to connect to the database.";
};
password-file = mkOption {
type = types.path;
description = "Password to use when connecting to the database.";
};
};
};
in {
options.fudo.webmail = {
enable = mkEnableOption "Enable a RainLoop webmail server.";
sites = mkOption {
type = with types; (loaOf (submodule siteOpts));
description = "A map of webmail sites to site configurations.";
example = {
"webmail.domain.com" = {
title = "My Awesome Webmail";
layout-mode = "side";
favicon = "/path/to/favicon.ico";
admin-password = "shh-don't-tell";
};
};
};
};
config = mkIf cfg.enable {
users = {
users = {
${webmail-user} = {
isSystemUser = true;
description = "Webmail PHP FPM user";
group = webmail-group;
};
};
groups = {
${webmail-group} = {
members = [ webmail-user config.services.nginx.user ];
};
};
};
services = {
phpfpm = {
pools.webmail = {
settings = {
"pm" = "dynamic";
"pm.max_children" = 50;
"pm.start_servers" = 5;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 8;
};
# Not working....see chmod below
user = webmail-user;
group = webmail-group;
};
};
nginx = {
enable = true;
virtualHosts = mapAttrs (site: site-cfg: {
enableACME = true;
forceSSL = true;
root = "${site-packages.${site}}";
locations = {
"/" = {
index = "index.php";
};
"/data" = {
extraConfig = ''
deny all;
return 403;
'';
};
};
extraConfig = ''
location ~ \.php$ {
expires -1;
include ${fastcgi-conf};
fastcgi_index index.php;
fastcgi_pass unix:${config.services.phpfpm.pools.webmail.socket};
}
'';
})
cfg.sites;
};
};
systemd.services.nginx.preStart = let
link-configs = concatStringsSep "\n" (mapAttrsToList (site: site-cfg: let
cfg-file = builtins.toFile "${site}-rainloop.cfg" (import ./include/rainloop.nix lib site site-cfg site-packages.${site}.version);
domain-cfg = builtins.toFile "${site}-domain.cfg" ''
imap_host = "${site-cfg.mail-server}"
imap_port = 143
imap_secure = "TLS"
imap_short_login = On
sieve_use = Off
sieve_allow_raw = Off
sieve_host = ""
sieve_port = 4190
sieve_secure = "None"
smtp_host = "${site-cfg.mail-server}"
smtp_port = 587
smtp_secure = "TLS"
smtp_short_login = On
smtp_auth = On
smtp_php_mail = Off
white_list = ""
'';
in ''
mkdir -p ${base-data-path}/${site}/_data_/_default_/configs
cp ${cfg-file} ${base-data-path}/${site}/_data_/_default_/configs/application.ini
mkdir -p ${base-data-path}/${site}/_data_/_default_/domains/
cp ${domain-cfg} ${base-data-path}/${site}/_data_/_default_/domains/${site-cfg.domain}.ini
'') cfg.sites);
in ''
${link-configs}
chown -R ${webmail-user}:${webmail-group} ${base-data-path}
chmod -R ug+w ${base-data-path}
'';
systemd.services.phpfpm-webmail.postStart = ''
chown ${webmail-user}:${webmail-group} ${config.services.phpfpm.pools.webmail.socket}
'';
};
}

View File

@ -5,6 +5,7 @@ with lib;
imports = [ imports = [
./fudo/acme-for-hostname.nix ./fudo/acme-for-hostname.nix
./fudo/authentication.nix ./fudo/authentication.nix
./fudo/chat.nix
./fudo/common.nix ./fudo/common.nix
./fudo/grafana.nix ./fudo/grafana.nix
./fudo/kdc.nix ./fudo/kdc.nix
@ -14,8 +15,10 @@ with lib;
./fudo/minecraft-server.nix ./fudo/minecraft-server.nix
./fudo/node-exporter.nix ./fudo/node-exporter.nix
./fudo/postgres.nix ./fudo/postgres.nix
./fudo/profiles.nix
./fudo/prometheus.nix ./fudo/prometheus.nix
./fudo/sites.nix ./fudo/webmail.nix
../fudo/profiles
../fudo/sites
]; ];
} }

View File

@ -9,7 +9,6 @@ in {
domain = "fudo.org"; domain = "fudo.org";
local-domains = [ local-domains = [
"fudo.org"
"mail.fudo.org" "mail.fudo.org"
"${config.networking.hostName}" "${config.networking.hostName}"
"selby.ca" "selby.ca"
@ -23,6 +22,7 @@ in {
"selbyhomecentre.com" "selbyhomecentre.com"
"stewartsoundservices.ca" "stewartsoundservices.ca"
"rogerwongphoto.com" "rogerwongphoto.com"
"chat.fudo.org"
]; ];
alias-users = import ./alias-users.nix; alias-users = import ./alias-users.nix;

View File

@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
imports = [
./desktop.nix
./server.nix
];
}

154
fudo/profiles/desktop.nix Normal file
View File

@ -0,0 +1,154 @@
{ config, lib, pkgs, ... }:
with lib;
{
config = mkIf (config.fudo.common.profile == "desktop") {
environment.systemPackages = with pkgs; [
cool-retro-term
chrome-gnome-shell
chromium
ffmpeg-full
firefox
gimp
glxinfo
gnome3.gnome-shell
gnome3.gnome-session
google-chrome
gtk2
gtk2-x11
gtk3
gtkimageview
i3lock
libfixposix
minecraft
mplayer
nomacs
openssl_1_1
redshift
rhythmbox
shotwell
spotify
sqlite
steam
system-config-printer
virtmanager
xorg.xev
xzgv
virtmanager-qt
];
# Splash screen
boot.plymouth.enable = true;
services.avahi = {
enable = true;
browseDomains = [config.fudo.domain];
domainName = config.fudo.domain;
};
boot.tmpOnTmpfs = true;
services.xserver = {
enable = true;
layout = "us";
xkbVariant = "dvp";
xkbOptions = "ctrl:nocaps";
desktopManager.gnome3.enable = true;
desktopManager.default = "gnome3";
displayManager.gdm.enable = true;
windowManager.session = pkgs.lib.singleton {
name = "stumpwm";
start = ''
${pkgs.lispPackages.stumpwm}/bin/stumpwm &
waidPID=$!
'';
};
};
services.printing = {
enable = true;
};
services.gnome3 = {
evolution-data-server.enable = pkgs.lib.mkForce false;
gnome-user-share.enable = pkgs.lib.mkForce false;
};
services.dbus.socketActivated = true;
services.openssh.forwardX11 = true;
programs.ssh.forwardX11 = true;
sound.enable = true;
hardware.pulseaudio.enable = true;
fonts = {
enableCoreFonts = true;
enableFontDir = true;
enableGhostscriptFonts = false;
fontconfig.ultimate.enable = true;
fonts = with pkgs; [
cantarell_fonts
dejavu_fonts
dina-font
dosemu_fonts
fira-code
fira-code-symbols
freefont_ttf
liberation_ttf
mplus-outline-fonts
nerdfonts
noto-fonts
noto-fonts-cjk
noto-fonts-emoji
proggyfonts
terminus_font
ubuntu_font_family
ucsFonts
unifont
vistafonts
xlibs.fontadobe100dpi
xlibs.fontadobe75dpi
xlibs.fontadobeutopia100dpi
xlibs.fontadobeutopia75dpi
xlibs.fontadobeutopiatype1
xlibs.fontarabicmisc
xlibs.fontbh100dpi
xlibs.fontbh75dpi
xlibs.fontbhlucidatypewriter100dpi
xlibs.fontbhlucidatypewriter75dpi
xlibs.fontbhttf
xlibs.fontbhtype1
xlibs.fontbitstream100dpi
xlibs.fontbitstream75dpi
xlibs.fontbitstreamtype1
xlibs.fontcronyxcyrillic
xlibs.fontcursormisc
xlibs.fontdaewoomisc
xlibs.fontdecmisc
xlibs.fontibmtype1
xlibs.fontisasmisc
xlibs.fontjismisc
xlibs.fontmicromisc
xlibs.fontmisccyrillic
xlibs.fontmiscethiopic
xlibs.fontmiscmeltho
xlibs.fontmiscmisc
xlibs.fontmuttmisc
xlibs.fontschumachermisc
xlibs.fontscreencyrillic
xlibs.fontsonymisc
xlibs.fontsunmisc
xlibs.fontwinitzkicyrillic
xlibs.fontxfree86type1
];
};
};
}

80
fudo/profiles/server.nix Normal file
View File

@ -0,0 +1,80 @@
{ config, lib, pkgs, ... }:
with lib;
let
reboot-if-necessary = pkgs.writeScriptBin "reboot-if-necessary" ''
#!${pkgs.stdenv.shell}
set -ne
if [ $# -ne 1 ]; then
echo "FAILED: no sync file provided."
exit 1
fi
WALL=${pkgs.utillinux}/bin/wall
if [ -f $1 ]; then
$WALL "$1 exists, rebooting system"
${pkgs.systemd}/bin/reboot
else
$WALL "$1 does not exist, aborting reboot."
fi
exit 0
'';
test-config = pkgs.writeScriptBin "fudo-test-config" ''
#!${pkgs.stdenv.shell}
set -ne
if [ $# -gt 1 ]; then
echo "usage: $0 [timeout]"
exit 1
elif [ $# -eq 1 ]; then
TIMEOUT=$1
else
TIMEOUT=15m
fi
SYNCFILE=$TMP/sync-$(date +"%Y%m%d-%H%M%N")
touch $SYNCFILE
${pkgs.utillinux}/bin/wall "Launching config. System will restart in $TIMEOUT if $SYNCFILE still exists."
systemd-run --on-active=$TIMEOUT ${reboot-if-necessary} $SYNCFILE
nixos-rebuild test
exit 0
'';
in {
config = mkIf (config.fudo.common.profile == "server") {
environment = {
systemPackages = with pkgs; [
test-config
reboot-if-necessary
];
noXlibs = true;
};
security = {
hideProcessInformation = true;
};
networking = {
networkmanager.enable = mkForce false;
};
boot.tmpOnTmpfs = true;
services.xserver.enable = false;
programs = {
gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
};
};
}

8
fudo/sites/default.nix Normal file
View File

@ -0,0 +1,8 @@
{ config, lib, pkgs, ... }:
{
imports = [
./portage.nix
./seattle.nix
];
}

60
fudo/sites/portage.nix Normal file
View File

@ -0,0 +1,60 @@
{ config, lib, pkgs, ... }:
with lib;
let
admin = "admin@fudo.org";
nameservers = [
"1.1.1.1"
"208.81.7.14"
"2606:4700:4700::1111"
];
hostname = config.networking.hostName;
gateway = "208.81.3.113";
gateway6 = "2605:e200:d200:1::1";
in {
config = mkIf (config.fudo.common.site == "portage") {
time.timeZone = "America/Winnipeg";
services.cron = {
mailto = admin;
};
networking = {
domain = "fudo.org";
search = ["fudo.org"];
firewall.enable = false;
nameservers = nameservers;
defaultGateway = gateway;
# defaultGateway6 = gateway6;
};
fudo.node-exporter = {
enable = true;
hostname = hostname;
};
security.acme.certs.${hostname} = {
email = "admin@fudo.org";
# plugins = [
# "fullchain.pem"
# "full.pem"
# "key.pem"
# "chain.pem"
# "cert.pem"
# ];
};
# TODO: We...could run nginx in a container
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
};
};
}

201
fudo/sites/seattle.nix Normal file
View File

@ -0,0 +1,201 @@
{ lib, config, pkgs, ... }:
with lib;
let
admin = "niten@fudo.org";
local-domain = "sea.fudo.org";
in {
config = mkIf (config.fudo.common.site == "seattle") {
time.timeZone = "America/Los_Angeles";
services.cron = {
mailto = admin;
};
networking = {
domain = local-domain;
search = [local-domain "fudo.org"];
firewall.enable = false;
networkmanager.enable = pkgs.lib.mkForce false;
# Until Comcast gets it's shit together... :(
enableIPv6 = false;
};
users.extraUsers = {
guest = {
isNormalUser = true;
uid = 1000;
description = "Guest User";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
};
ken = {
isNormalUser = true;
uid = 10035;
createHome = true;
description = "Ken Selby";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
group = "users";
home = "/home/selby/ken";
hashedPassword = "$6$EwK9fpbH8$gYVzYY1IYw2/G0wCeUxXrZZqvjWCkCZbBqCOhxowbMuYtC5G0vp.AoYhVKWOJcHJM2c7TdPmAdnhLIe2KYStf.";
};
xiaoxuan = {
isNormalUser = true;
uid = 10065;
createHome = true;
description = "Xiaoxuan Jin";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
group = "users";
home = "/home/xiaoxuan";
hashedPassword = "$6$C8lYHrK7KvdKm/RE$cHZ2hg5gEOEjTV8Zoayik8sz5h.Vh0.ClCgOlQn8l/2Qx/qdxqZ7xCsAZ1GZ.IEyESfhJeJbjLpykXDwPpfVF0";
};
};
fileSystems."/mnt/documents" = {
device = "whitedwarf.${local-domain}:/volume1/Documents";
fsType = "nfs4";
};
fileSystems."/mnt/downloads" = {
device = "whitedwarf.${local-domain}:/volume1/Downloads";
fsType = "nfs4";
};
fileSystems."/mnt/music" = {
device = "doraemon.${local-domain}:/volume1/Music";
fsType = "nfs4";
};
fileSystems."/mnt/video" = {
device = "doraemon.${local-domain}:/volume1/Video";
fsType = "nfs4";
};
# fileSystems."/mnt/security" = {
# device = "panopticon.${local-domain}:/srv/kerberos/data";
# fsType = "nfs4";
# };
fileSystems."/mnt/cargo_video" = {
device = "cargo.${local-domain}:/volume1/video";
fsType = "nfs4";
};
fileSystems."/mnt/photo" = {
device = "cargo.${local-domain}:/volume1/pictures";
fsType = "nfs4";
};
# Should use this eventually...
# fudo.localNetwork = {
# masterNameServer = {
# ip = "10.0.0.1";
# ipReverseDomain = "0.10.in-addr.arpa";
# };
# domain = "${local-domain}";
# hostAliases = {
# kadmin = "slab";
# kdc = "slab";
# photo = "doraemon";
# music = "doraemon";
# panopticon = "hyperion";
# hole = "dnshole";
# ipfs = "nostromo";
# };
# hosts = {
# slab = {
# ipv4Address = "10.0.0.1";
# };
# volsung = {
# ipv4Address = "10.0.0.106";
# macAddress = "ac:bc:32:7b:75:a5";
# };
# nest = {
# ipv4Address = "10.0.0.176";
# macAddress = "18:b4:30:16:7c:5a";
# };
# monolith = {
# ipv4Address = "10.0.0.100";
# macAddress = "6c:62:6d:c8:b0:d8";
# };
# brother-wireless = {
# ipv4Address = "10.0.0.160";
# macAddress = "c0:38:96:64:49:65";
# };
# doraemon = {
# ipv4Address = "10.0.0.52";
# macAddress = "00:11:32:0a:06:c5";
# };
# lm = {
# ipv4Address = "10.0.0.21";
# macAddress = "52:54:00:D8:34:92";
# };
# ubiquiti-wifi = {
# ipv4Address = "10.0.0.126";
# macAddress = "04:18:d6:20:48:fb";
# };
# front-light = {
# ipv4Address = "10.0.0.221";
# macAddress = "94:10:3e:48:94:ed";
# };
# ipad = {
# ipv4Address = "10.0.0.202";
# macAddress = "9c:35:eb:48:6e:71";
# };
# chromecast-2 = {
# ipv4Address = "10.0.0.215";
# macAddress = "a4:77:33:59:a2:ba";
# };
# taipan = {
# ipv4Address = "10.0.0.107";
# macAddress = "52:54:00:34:c4:78";
# };
# dns-hole = {
# ipv4Address = "10.0.0.185";
# macAddress = "b8:27:eb:b2:95:fd";
# };
# family-tv = {
# ipv4Address = "10.0.0.205";
# macAddress = "84:a4:66:3a:b1:f8";
# };
# spark = {
# ipv4Address = "10.0.0.108";
# macAddress = "78:24:af:04:f7:dd";
# };
# babycam = {
# ipv4Address = "10.0.0.206";
# macAddress = "08:ea:40:59:5f:9e";
# };
# hyperion = {
# ipv4Address = "10.0.0.109";
# macAddress = "52:54:00:33:46:de";
# };
# cargo = {
# ipv4Address = "10.0.0.50";
# macAddress = "00:11:32:75:d8:b7";
# };
# cam-entrance = {
# ipv4Address = "10.0.0.31";
# macAddress = "9c:8e:cd:0e:99:7b";
# };
# cam-driveway = {
# ipv4Address = "10.0.0.32";
# macAddress = "9c:8e:cd:0d:3b:09";
# };
# cam-deck = {
# ipv4Address = "10.0.0.33";
# macAddress = "9c:8e:cd:0e:98:c8";
# };
# nostromo = {
# ipv4Address = "10.0.0.2";
# macAddress = "14:fe:b5:ca:a2:c9";
# };
# zbox = {
# ipv4Address = "10.0.0.110";
# macAddress = "18:60:24:91:CC:27";
# };
# };
# };
};
}

View File

@ -408,4 +408,11 @@
hashed-password = "{SSHA}LSz1WjWfjRwAM3xm+QZ71vFj997dnZC6"; hashed-password = "{SSHA}LSz1WjWfjRwAM3xm+QZ71vFj997dnZC6";
}; };
# Used to send messages from the chat server
chat = {
uid = 10111;
group = "fudo";
common-name = "Fudo Chat";
hashed-password = "{SSHA}XDYAM2JE4PXssywRzO4tVSbn5lUZOgg7";
};
} }

View File

@ -2,8 +2,9 @@
with lib; with lib;
let let
hostname = "france.fudo.org"; domain = "fudo.org";
mail-hostname = "france.fudo.org"; hostname = "france.${domain}";
mail-hostname = hostname;
host_ipv4 = "208.81.3.117"; host_ipv4 = "208.81.3.117";
all-hostnames = []; all-hostnames = [];
@ -29,20 +30,26 @@ in {
../hardware-configuration.nix ../hardware-configuration.nix
../defaults.nix ../defaults.nix
# These should really both be settings...
# ../networks/fudo.org.nix
# ../profiles/server.nix
]; ];
fudo.profile = "server"; fudo.common = {
fudo.site = "nutty-club"; # Sets some server-common settings. See /etc/nixos/fudo/profiles/...
fudo.local-networks = [ profile = "server";
"208.81.1.128/28"
"208.81.3.112/28" # Sets some common site-specific settings: gateway, monitoring, etc. See /etc/nixos/fudo/sites/...
"172.17.0.0/16" site = "portage";
"127.0.0.0/8"
]; domain = domain;
www-root = /srv/www;
local-networks = [
"208.81.1.128/28"
"208.81.3.112/28"
"172.17.0.0/16"
"127.0.0.0/8"
];
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
docker docker
@ -60,14 +67,6 @@ in {
dovecot = [ "dovecot._metrics._tcp.fudo.org" ]; dovecot = [ "dovecot._metrics._tcp.fudo.org" ];
rspamd = [ "rspamd._metrics._tcp.fudo.org" ]; rspamd = [ "rspamd._metrics._tcp.fudo.org" ];
}; };
# Connections will be allowed from these networks. No auth is performed--the
# data is read-only anyway.
trusted-networks = [
"208.81.1.128/28"
"208.81.3.112/28"
"172.17.0.0/16"
"127.0.0.0/8"
];
}; };
fudo.grafana = { fudo.grafana = {
@ -75,15 +74,20 @@ in {
hostname = "monitor.fudo.org"; hostname = "monitor.fudo.org";
smtp-username = "metrics"; smtp-username = "metrics";
smtp-password-file = "/srv/grafana/secure/smtp.passwd"; smtp-password-file = "/srv/grafana/secure/smtp.passwd";
database-password-file = "/srv/grafana/secure/db.passwd";
admin-password-file = "/srv/grafana/secure/admin.passwd"; admin-password-file = "/srv/grafana/secure/admin.passwd";
secret-key-file = "/srv/grafana/secure/secret.key"; secret-key-file = "/srv/grafana/secure/secret.key";
prometheus-host = "metrics.fudo.org"; prometheus-host = "metrics.fudo.org";
database = {
name = "grafana";
hostname = "localhost";
user = "grafana";
password-file = /srv/grafana/secure/db.passwd;
};
}; };
# So that grafana waits for postgresql # So that grafana waits for postgresql
systemd.services.grafana.requires = [ systemd.services.grafana.after = [
"postgresql" "postgresql.service"
]; ];
fudo.postgresql = { fudo.postgresql = {
@ -95,7 +99,7 @@ in {
# We allow connections from local networks. Auth is still required. Outside # We allow connections from local networks. Auth is still required. Outside
# of these networks, no access is allowed. # of these networks, no access is allowed.
# #
# TODO: that's probably to strict, allow kerberos connections from anywhere. # TODO: that's probably too strict, allow kerberos connections from anywhere?
local-networks = [ local-networks = [
"208.81.1.128/28" "208.81.1.128/28"
"208.81.3.112/28" "208.81.3.112/28"
@ -103,6 +107,34 @@ in {
"127.0.0.1/8" "127.0.0.1/8"
"172.17.0.0/16" "172.17.0.0/16"
]; ];
users = {
grafana = {
password = fileContents "/srv/grafana/secure/db.passwd";
databases = {
grafana = "ALL PRIVILEGES";
};
};
mattermost = {
password = fileContents "/srv/mattermost/secure/db.passwd";
databases = {
mattermost = "ALL PRIVILEGES";
};
};
webmail = {
password = fileContents "/srv/webmail/secure/db.passwd";
databases = {
webmail = "ALL PRIVILEGES";
};
};
niten = {};
};
databases = {
grafana = ["niten"];
mattermost = ["niten"];
webmail = ["niten"];
};
}; };
# Not all users need access to france; don't allow LDAP-user access. # Not all users need access to france; don't allow LDAP-user access.
@ -133,10 +165,14 @@ in {
# TODO: loop over v4 and v6 IPs. # TODO: loop over v4 and v6 IPs.
listen-uris = [ listen-uris = [
"ldap://${host_ipv4}/" "ldap:///"
"ldaps://${host_ipv4}/" "ldaps:///"
"ldap://localhost/" # "ldap://${host_ipv4}/"
"ldaps://localhost/" # "ldaps://${host_ipv4}/"
# "ldap://localhost/"
# "ldaps://localhost/"
# "ldap://127.0.1.1/"
# "ldaps://127.0.1.1/"
"ldapi:///" "ldapi:///"
]; ];
@ -191,13 +227,51 @@ in {
dkim.signing = true; dkim.signing = true;
}; };
fudo.webmail = {
enable = true;
sites = {
"webmail.fudo.link" = {
title = "Fudo Link Webmail";
favicon = "/etc/nixos/static/fudo.link/favicon.ico";
mail-server = mail-hostname;
domain = "fudo.link";
edit-mode = "Plain";
layout-mode = "bottom";
database = {
name = "webmail";
hostname = "localhost";
user = "webmail";
password-file = /srv/webmail/secure/db.passwd;
};
};
};
};
fudo.chat = {
enable = true;
hostname = "chat.fudo.org";
site-name = "Fudo Chat";
smtp-server = "france.fudo.org";
smtp-user = "chat";
smtp-password-file = /srv/mattermost/secure/smtp.passwd;
database = {
name = "mattermost";
hostname = "localhost";
user = "mattermost";
password-file = /srv/mattermost/secure/db.passwd;
};
};
networking = { networking = {
hostName = hostname; hostName = hostname;
dhcpcd.enable = false; dhcpcd.enable = false;
useDHCP = false; useDHCP = false;
interfaces.enp4s0f0.useDHCP = true; # Why on earth would these use DHCP?
interfaces.enp4s0f1.useDHCP = true; # interfaces.enp4s0f0.useDHCP = true;
# interfaces.enp4s0f1.useDHCP = true;
# TODO: fix IPv6 # TODO: fix IPv6
enableIPv6 = false; enableIPv6 = false;
@ -276,6 +350,16 @@ in {
options = ["subvol=gitlab"]; options = ["subvol=gitlab"];
label = "pool0"; label = "pool0";
}; };
"/var/lib/lxd/storage-pools/pool0" = {
fsType = "btrfs";
label = "pool0";
device = "/dev/disk/by-label/pool0";
};
"/var/lib/lxd/storage-pools/pool1" = {
fsType = "btrfs";
label = "pool1";
device = "/dev/france-user/fudo-user";
};
}; };
## ##

View File

@ -1,112 +0,0 @@
{ lib, config, pkgs, ... }:
let
hostname = config.networking.hostName;
www-root = "/var/www";
index = pkgs.writeTextFile {
name = "index.html";
text = ''
<html>
<head>
<title>${hostname}</title>
</head>
<body>
<h1>${hostname}</title>
</body>
</html>
'';
destination = www-root + ("/" + hostname);
};
in {
config = {
time.timeZone = "America/Winnipeg";
services.cron = {
mailto = "admin@fudo.org";
};
networking = {
domain = "fudo.org";
search = ["fudo.org"];
firewall.enable = false;
networkmanager.enable = pkgs.lib.mkForce false;
defaultGateway = "208.81.3.113";
nameservers = [ "1.1.1.1" "208.81.7.14" "2606:4700:4700::1111" ];
};
security.acme.certs."${hostname}" = {
email = "admin@fudo.org";
plugins = [
"fullchain.pem"
"full.pem"
"key.pem"
"chain.pem"
"cert.pem"
];
};
services = {
prometheus.exporters.node = {
enable = true;
enabledCollectors = [ "systemd" ];
user = "node";
};
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
virtualHosts = {
"${hostname}" = {
enableACME = true;
forceSSL = true;
root = www-root + ("/" + hostname);
listen = [
{
addr = hostname;
port = 80;
ssl = false;
}
{
addr = hostname;
port = 443;
ssl = true;
}
];
locations."/metrics/node" = {
extraConfig = ''
allow 208.81.1.128/28;
allow 208.81.3.112/28;
allow 127.0.0.0/16;
deny all;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
'';
# proxy_set_header Host $http_host;
proxyPass = "http://127.0.0.1:9100/metrics";
};
};
};
};
};
};
}

View File

@ -1,192 +0,0 @@
{ config, pkgs, ... }:
{
config.time.timeZone = "America/Los_Angeles";
config.services.cron = {
mailto = "niten@fudo.org";
};
services.printing.enable = true;
config.networking = {
domain = "sea.fudo.org";
search = ["sea.fudo.org" "fudo.org"];
firewall.enable = false;
networkmanager.enable = pkgs.lib.mkForce false;
# Until Comcast gets it's shit together... :(
enableIPv6 = false;
};
config.fileSystems."/mnt/documents" = {
device = "whitedwarf.sea.fudo.org:/volume1/Documents";
fsType = "nfs4";
};
config.fileSystems."/mnt/downloads" = {
device = "whitedwarf.sea.fudo.org:/volume1/Downloads";
fsType = "nfs4";
};
config.fileSystems."/mnt/music" = {
device = "doraemon.sea.fudo.org:/volume1/Music";
fsType = "nfs4";
};
config.fileSystems."/mnt/video" = {
device = "doraemon.sea.fudo.org:/volume1/Video";
fsType = "nfs4";
};
# fileSystems."/mnt/security" = {
# device = "panopticon.sea.fudo.org:/srv/kerberos/data";
# fsType = "nfs4";
# };
config.fileSystems."/mnt/cargo_video" = {
device = "cargo.sea.fudo.org:/volume1/video";
fsType = "nfs4";
};
config.fileSystems."/mnt/photo" = {
device = "cargo.sea.fudo.org:/volume1/pictures";
fsType = "nfs4";
};
config.users.extraUsers = {
guest = {
isNormalUser = true;
uid = 1000;
description = "Guest User";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
};
ken = {
isNormalUser = true;
uid = 10035;
createHome = true;
description = "Ken Selby";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
group = "users";
home = "/home/selby/ken";
hashedPassword = "$6$EwK9fpbH8$gYVzYY1IYw2/G0wCeUxXrZZqvjWCkCZbBqCOhxowbMuYtC5G0vp.AoYhVKWOJcHJM2c7TdPmAdnhLIe2KYStf.";
};
xiaoxuan = {
isNormalUser = true;
uid = 10065;
createHome = true;
description = "Xiaoxuan Jin";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
group = "users";
home = "/home/xiaoxuan";
hashedPassword = "$6$C8lYHrK7KvdKm/RE$cHZ2hg5gEOEjTV8Zoayik8sz5h.Vh0.ClCgOlQn8l/2Qx/qdxqZ7xCsAZ1GZ.IEyESfhJeJbjLpykXDwPpfVF0";
};
};
config.fudo.localNetwork = {
masterNameServer = {
ip = "10.0.0.1";
ipReverseDomain = "0.10.in-addr.arpa";
};
domain = "sea.fudo.org";
hostAliases = {
kadmin = "slab";
kdc = "slab";
photo = "doraemon";
music = "doraemon";
panopticon = "hyperion";
hole = "dnshole";
ipfs = "nostromo";
};
hosts = {
slab = {
ipv4Address = "10.0.0.1";
};
volsung = {
ipv4Address = "10.0.0.106";
macAddress = "ac:bc:32:7b:75:a5";
};
nest = {
ipv4Address = "10.0.0.176";
macAddress = "18:b4:30:16:7c:5a";
};
monolith = {
ipv4Address = "10.0.0.100";
macAddress = "6c:62:6d:c8:b0:d8";
};
brother-wireless = {
ipv4Address = "10.0.0.160";
macAddress = "c0:38:96:64:49:65";
};
doraemon = {
ipv4Address = "10.0.0.52";
macAddress = "00:11:32:0a:06:c5";
};
lm = {
ipv4Address = "10.0.0.21";
macAddress = "52:54:00:D8:34:92";
};
ubiquiti-wifi = {
ipv4Address = "10.0.0.126";
macAddress = "04:18:d6:20:48:fb";
};
front-light = {
ipv4Address = "10.0.0.221";
macAddress = "94:10:3e:48:94:ed";
};
ipad = {
ipv4Address = "10.0.0.202";
macAddress = "9c:35:eb:48:6e:71";
};
chromecast-2 = {
ipv4Address = "10.0.0.215";
macAddress = "a4:77:33:59:a2:ba";
};
taipan = {
ipv4Address = "10.0.0.107";
macAddress = "52:54:00:34:c4:78";
};
dns-hole = {
ipv4Address = "10.0.0.185";
macAddress = "b8:27:eb:b2:95:fd";
};
family-tv = {
ipv4Address = "10.0.0.205";
macAddress = "84:a4:66:3a:b1:f8";
};
spark = {
ipv4Address = "10.0.0.108";
macAddress = "78:24:af:04:f7:dd";
};
babycam = {
ipv4Address = "10.0.0.206";
macAddress = "08:ea:40:59:5f:9e";
};
hyperion = {
ipv4Address = "10.0.0.109";
macAddress = "52:54:00:33:46:de";
};
cargo = {
ipv4Address = "10.0.0.50";
macAddress = "00:11:32:75:d8:b7";
};
cam-entrance = {
ipv4Address = "10.0.0.31";
macAddress = "9c:8e:cd:0e:99:7b";
};
cam-driveway = {
ipv4Address = "10.0.0.32";
macAddress = "9c:8e:cd:0d:3b:09";
};
cam-deck = {
ipv4Address = "10.0.0.33";
macAddress = "9c:8e:cd:0e:98:c8";
};
nostromo = {
ipv4Address = "10.0.0.2";
macAddress = "14:fe:b5:ca:a2:c9";
};
zbox = {
ipv4Address = "10.0.0.110";
macAddress = "18:60:24:91:CC:27";
};
};
};
}

View File

@ -1 +0,0 @@
root@france.26610:1573312038

View File

@ -1,151 +0,0 @@
{ config, lib, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
cool-retro-term
chrome-gnome-shell
chromium
ffmpeg-full
firefox
gimp
glxinfo
gnome3.gnome-shell
gnome3.gnome-session
google-chrome
gtk2
gtk2-x11
gtk3
gtkimageview
i3lock
libfixposix
minecraft
mplayer
nomacs
openssl_1_1
redshift
rhythmbox
shotwell
spotify
sqlite
steam
system-config-printer
virtmanager
xorg.xev
xzgv
virtmanager-qt
];
boot.plymouth.enable = true;
services.avahi = {
enable = true;
browseDomains = ["sea.fudo.org"];
domainName = "sea.fudo.org";
};
boot.tmpOnTmpfs = true;
services.xserver = {
enable = true;
layout = "us";
xkbVariant = "dvp";
xkbOptions = "ctrl:nocaps";
desktopManager.gnome3.enable = true;
desktopManager.default = "gnome3";
displayManager.gdm.enable = true;
windowManager.session = pkgs.lib.singleton {
name = "stumpwm";
start = ''
${pkgs.lispPackages.stumpwm}/bin/stumpwm &
waidPID=$!
'';
};
};
services.printing = {
enable = true;
};
services.gnome3 = {
evolution-data-server.enable = pkgs.lib.mkForce false;
gnome-user-share.enable = pkgs.lib.mkForce false;
};
services.dbus.socketActivated = true;
services.openssh.forwardX11 = true;
programs.ssh.forwardX11 = true;
sound.enable = true;
hardware.pulseaudio.enable = true;
fonts = {
enableCoreFonts = true;
enableFontDir = true;
enableGhostscriptFonts = false;
fontconfig.ultimate.enable = true;
fonts = with pkgs; [
cantarell_fonts
dejavu_fonts
dina-font
dosemu_fonts
fira-code
fira-code-symbols
freefont_ttf
liberation_ttf
mplus-outline-fonts
nerdfonts
noto-fonts
noto-fonts-cjk
noto-fonts-emoji
proggyfonts
terminus_font
ubuntu_font_family
ucsFonts
unifont
vistafonts
xlibs.fontadobe100dpi
xlibs.fontadobe75dpi
xlibs.fontadobeutopia100dpi
xlibs.fontadobeutopia75dpi
xlibs.fontadobeutopiatype1
xlibs.fontarabicmisc
xlibs.fontbh100dpi
xlibs.fontbh75dpi
xlibs.fontbhlucidatypewriter100dpi
xlibs.fontbhlucidatypewriter75dpi
xlibs.fontbhttf
xlibs.fontbhtype1
xlibs.fontbitstream100dpi
xlibs.fontbitstream75dpi
xlibs.fontbitstreamtype1
xlibs.fontcronyxcyrillic
xlibs.fontcursormisc
xlibs.fontdaewoomisc
xlibs.fontdecmisc
xlibs.fontibmtype1
xlibs.fontisasmisc
xlibs.fontjismisc
xlibs.fontmicromisc
xlibs.fontmisccyrillic
xlibs.fontmiscethiopic
xlibs.fontmiscmeltho
xlibs.fontmiscmisc
xlibs.fontmuttmisc
xlibs.fontschumachermisc
xlibs.fontscreencyrillic
xlibs.fontsonymisc
xlibs.fontsunmisc
xlibs.fontwinitzkicyrillic
xlibs.fontxfree86type1
];
};
}

View File

@ -1,19 +0,0 @@
{ config, pkgs, ... }:
let
base = "dc=fudo,dc=org";
ldap = import ../config/fudo/ldap.nix;
in {
imports = [
../config/fudo/ldap.nix
];
services.openldap = {
enable = true;
suffix = base;
rootdn = "cn=admin,${base}";
rootpwFile = "/srv/ldap/secure/root.pw";
};
}

View File

@ -1,16 +0,0 @@
{ config, pkgs, ... }:
{
environment = {
systemPackages = with pkgs; [
];
noXlibs = true;
};
security.hideProcessInformation = true;
boot.tmpOnTmpfs = true;
services.xserver.enable = false;
}

View File

@ -1,43 +0,0 @@
# Starts an Nginx server on $HOSTNAME just to get a cert for this host
{ config, pkgs, environment, ... }:
let
hostname = config.networking.hostName;
wwwRoot = pkgs.writeTextFile {
name = "index.html";
text = ''
<html>
<head>
<title>${hostname}</title>
</head>
<body>
<h1>${hostname}</title>
</body>
</html>
'';
destination = "/www";
};
in {
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
virtualHosts."${hostname}" = {
enableACME = true;
forceSSL = true;
root = wwwRoot + ("/" + "www");
};
};
security.acme.certs = {
${hostname}.email = "admin@fudo.org";
};
}

View File

@ -1,136 +0,0 @@
{ config, pkgs, environment, ... }:
let
databaseName = "powerdns";
userName = "powerdns";
reverseIp = ip: builtins.concatStringsSep "." (lib.lists.reverseList(lib.strings.splitString "." ip));
fullReverseIp = ip: "${reverseIp ip}.in-addr.arpa";
hostRecord = domain_id: type: name: content: ''
INSERT INTO records (domain_id, name, type, content) VALUES ($domain_id, '${name}', '${type}', '${content}');
'';
in {
environment = {
systemPackages = with pkgs; [
postgresql_11_gssapi
powerdns
];
};
services.postgresql.users."${userName}" = {
passwd = "some_junk";
databases = ["${databaseName}"];
};
services.postgresql.databases."${databaseName} = {
"${databaseName}" = ''
CREATE TABLE domains (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
master VARCHAR(128) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL,
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
);
CREATE UNIQUE INDEX name_index ON domains(name);
CREATE TABLE records (
id BIGSERIAL PRIMARY KEY,
domain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(10) DEFAULT NULL,
content VARCHAR(65535) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
disabled BOOL DEFAULT 'f',
ordername VARCHAR(255),
auth BOOL DEFAULT 't',
CONSTRAINT domain_exists
FOREIGN KEY(domain_id) REFERENCES domains(id)
ON DELETE CASCADE,
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
);
CREATE INDEX rec_name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX recordorder ON records (domain_id, ordername text_pattern_ops);
CREATE TABLE supermasters (
ip INET NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) NOT NULL,
PRIMARY KEY(ip, nameserver)
);
CREATE TABLE comments (
id SERIAL PRIMARY KEY,
domain_id INT NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(10) NOT NULL,
modified_at INT NOT NULL,
account VARCHAR(40) DEFAULT NULL,
comment VARCHAR(65535) NOT NULL,
CONSTRAINT domain_exists
FOREIGN KEY(domain_id) REFERENCES domains(id)
ON DELETE CASCADE,
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
);
CREATE INDEX comments_domain_id_idx ON comments (domain_id);
CREATE INDEX comments_name_type_idx ON comments (name, type);
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);
CREATE TABLE domainmetadata (
id SERIAL PRIMARY KEY,
domain_id INT REFERENCES domains(id) ON DELETE CASCADE,
kind VARCHAR(32),
content TEXT
);
CREATE INDEX domainidmetaindex ON domainmetadata(domain_id);
CREATE TABLE cryptokeys (
id SERIAL PRIMARY KEY,
domain_id INT REFERENCES domains(id) ON DELETE CASCADE,
flags INT NOT NULL,
active BOOL,
content TEXT
);
CREATE INDEX domainidindex ON cryptokeys(domain_id);
CREATE TABLE tsigkeys (
id SERIAL PRIMARY KEY,
name VARCHAR(255),
algorithm VARCHAR(50),
secret VARCHAR(255),
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
);
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
INSERT INTO domains (id, name, master, type) VALUES (1, '${config.fudo.localNetwork.domain}', '${config.fudo.localNetwork.masterNameServer.ip}', 'MASTER');
INSERT INTO domains (id, name, master, type) VALUES (2, '${config.fudo.localNetwork.masterNameServer.ipReverseDomain}', '${config.fudo.localNetwork.masterNameServer.ip}', 'MASTER');
${hostRecord 1 "SOA" config.fudo.localDomain "${config.fudo.localNetwork.domain}. hostmaster.${config.fudo.localNetwork.domain}."}
${hostRecord 2 "SOA" config.fudo.masterNameServer.ipReverseDomain "${config.fudo.localNetwork.masterNameServer.ipReverseDomain} hostmaster.${config.fudo.localNetwork.domain}."}
${hostRecord 1 "NS" config.fudo.localNetwork.domain config.fudo.localNetwork.masterNameServer.ip}
${hostRecord 2 "NS" config.fudo.localNetwork.masterNameServer.ipReverseDomain config.fudo.localNetwork.masterNameServer.ip}
${builtins.concatStringsSep "\n" (lib.attrSets.mapAttrs (host: attrs: hostRecord 1 "A" host attrs.ipv4Address) config.fudo.localNetwork.hosts)}
${builtins.concatStringsSep "\n" (lib.attrSets.mapAttrs (host: attrs: hostRecord 2 "PTR" (fullReverseIp attrs.ipv4Address) host) config.fudo.localNetworkhosts)}
${builtins.concatStringsSep "\n" (lib.attrSets.mapAttrs (alias: host: hostRecord 1 "CNAME" alias host) config.fudo.localNetwork.hostAliases)}
'';
};
};
}

View File

@ -1,42 +0,0 @@
{ config, pkgs, ... }:
{ containers.https =
let
hostname = "${config.hostname}.fudo.link";
incomingCertDir = "/srv/${config.hostname}/certs";
containerCertsDir = "/etc/letsencrypt/live";
in {
autoStart = true;
bindMounts = [
{
"${containerCertsDir}" = {
hostPath = "${incomingCertsDir}";
isReadOnly = false;
};
}
];
config = { config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
nginx
];
services.nginx = {
enable = true;
virtualHosts."${hostname}" = {
enableACME = true;
forceSSL = true;
root = "/var/www";
};
security.acme.certs = {
"${hostname}".email = config.adminEmail;
};
};
};
};
}

View File

@ -1,75 +0,0 @@
{ config, pkgs, environment, ... }:
let
hostPath = /srv + ("/" + config.networking.hostName);
srcCertificateDirectory = hostPath + "/certs";
dstCertificateDirectory = "/etc/pki/certs/postgres";
dstPrivateKey = dstCertificateDirectory + /private/privkey.pem;
srcKeytabPath = hostPath + /keytabs/postgres;
dstKeytabPath = "/etc/postgresql-common/keytab";
in {
containers.postgres = {
autoStart = true;
bindMounts = {
"${dstCertificateDirectory}" = {
hostPath = "${srcCertificateDirectory}";
isReadOnly = false;
};
"${dstKeytabPath}" = {
hostPath = "${srcKeytabPath}";
isReadOnly = false;
};
};
config = { config, pkgs, environment, ... }: {
environment.etc."${dstPrivateKey}".mode = "0400";
boot.tmpOnTmpfs = true;
# Kind of a stupid hack...bindMounts can't specify perms, and it defaults to
# permissive (even for nested files). So, explicitly make the keys private.
# TODO: eventually, use bindMount perms, hopefully?
boot.postBootCommands = ''
chown postgres ${dstKeytabPath}/postgres.keytab
chmod 400 ${dstKeytabPath}/postgres.keytab
chown -R postgres ${dstCertificateDirectory}
chown 400 ${dstCertificateDirectory}/private/privkey.pem
'';
services.postgresql = {
enable = true;
package = pkgs.postgresql_10;
enableTCPIP = true;
extraConfig =
''
krb_server_keyfile = '${dstKeytabPath}/postgres.keytab'
ssl = true
ssl_cert_file = '${dstCertificateDirectory}/cert.pem'
ssl_key_file = '${dstCertificateDirectory}/private/privkey.pem'
'';
authentication =
''
local all all ident
# host-local
host all all 127.0.0.1/32 gss include_realm=0 krb_realm=FUDO.ORG
host all all ::1/128 gss include_realm=0 krb_realm=FUDO.ORG
# local network
host all all 10.0.0.1/24 gss include_realm=0 krb_realm=FUDO.ORG
host all all 2601:600:997f:fc00::/60 gss include_realm=0 krb_realm=FUDO.ORG
'';
initialScript = pkgs.writeText "backend-initscript" ''
CREATE ROLE niten;
'';
};
};
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}