In a pretty good working state
This commit is contained in:
parent
00a97b1d94
commit
2aa6b8efc6
|
@ -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;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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}"
|
||||||
|
''
|
|
@ -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
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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};
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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};
|
|
||||||
}
|
|
|
@ -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}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
|
@ -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
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./desktop.nix
|
||||||
|
./server.nix
|
||||||
|
];
|
||||||
|
}
|
|
@ -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
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./portage.nix
|
||||||
|
./seattle.nix
|
||||||
|
];
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -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";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
}
|
|
@ -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";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
138
hosts/france.nix
138
hosts/france.nix
|
@ -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";
|
||||||
|
|
||||||
|
# Sets some common site-specific settings: gateway, monitoring, etc. See /etc/nixos/fudo/sites/...
|
||||||
|
site = "portage";
|
||||||
|
|
||||||
|
domain = domain;
|
||||||
|
|
||||||
|
www-root = /srv/www;
|
||||||
|
|
||||||
|
local-networks = [
|
||||||
"208.81.1.128/28"
|
"208.81.1.128/28"
|
||||||
"208.81.3.112/28"
|
"208.81.3.112/28"
|
||||||
"172.17.0.0/16"
|
"172.17.0.0/16"
|
||||||
"127.0.0.0/8"
|
"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";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
root@france.26610:1573312038
|
|
|
@ -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
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -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";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
{ config, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
environment = {
|
|
||||||
systemPackages = with pkgs; [
|
|
||||||
];
|
|
||||||
|
|
||||||
noXlibs = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
security.hideProcessInformation = true;
|
|
||||||
|
|
||||||
boot.tmpOnTmpfs = true;
|
|
||||||
|
|
||||||
services.xserver.enable = false;
|
|
||||||
}
|
|
|
@ -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";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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)}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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 |
|
@ -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"}
|
Loading…
Reference in New Issue