nixos-config/config/host-config/nutboy3/forum_selby_ca.nix

277 lines
8.7 KiB
Nix
Raw Permalink Normal View History

2021-12-18 12:10:42 -08:00
{ config, lib, pkgs, ... }:
with lib;
let
site = "forum.test.selby.ca";
hostname = config.instance.hostname;
host-secrets = config.fudo.secrets.host-secrets.${hostname};
database-name = "forum_selby_ca";
database-user = "forum_selby_ca";
state-directory = "/state/selby/forum";
password-injector-sql = csv-file: pkgs.stdenv.mkDerivation {
name = "${site}-password-injector-sql";
phases = [ "installPhase" ];
buildInputs = [ pkgs.ruby ];
installPhase = ''
${password-convert-script csv-file}
'';
};
password-convert-script = csv-file: pkgs.writeScript "vanilla-forum-password-convert.rb" ''
#!${pkgs.ruby}/bin/ruby
require 'csv'
data = CSV::readlines("${csv-file}")
File::open(ENV["out"], "w") { |sql|
data.each { |row|
sql.puts("UPDATE users SET import_pass='#{row[2]}' FROM user_emails WHERE users.id = user_emails.user_id AND user_emails.email = '#{row[1]}';")
}
}
'';
2022-03-16 09:49:35 -07:00
head-pkgs = let
nixos = pkgs.fetchgit {
url = "https://github.com/nixos/nixpkgs.git";
rev = "21.11";
sha256 = "162dywda2dvfj1248afxc45kcrg83appjd0nmdb541hl7rnncf02";
2021-12-18 12:10:42 -08:00
};
2022-03-16 09:49:35 -07:00
in import "${nixos}" {
system = pkgs.system;
config = pkgs.config;
overlays = pkgs.overlays;
};
in {
config = let
admin-pw-file = "admin.passwd";
db-pw-file = "database.passwd";
data-file = "data-forum_selby_ca.txt";
in {
2021-12-18 12:10:42 -08:00
fudo = {
secrets.host-secrets.${hostname} = let
selby-discourse-db-password =
pkgs.lib.passwd.stablerandom-passwd-file
"selby-discourse-database-password"
"selby-discourse-database-password-${config.instance.build-seed}";
files = config.fudo.secrets.files;
in {
selby-discourse-database-passwd = {
source-file = selby-discourse-db-password;
2022-03-16 09:49:35 -07:00
target-file = "/run/selby/forum/${db-pw-file}";
user = "root";
2021-12-18 12:10:42 -08:00
};
postgresql-selby-discourse-password = {
source-file = selby-discourse-db-password;
target-file = "/run/postgres/selby-discourse.passwd";
user = config.services.postgresql.superUser;
};
selby-discourse-admin = {
source-file = pkgs.lib.passwd.stablerandom-passwd-file
"selby-discourse-admin"
"selby-discourse-admin-${config.instance.build-seed}";
2022-03-16 09:49:35 -07:00
target-file = "/run/selby/forum/${admin-pw-file}";
user = "root";
2021-12-18 12:10:42 -08:00
};
selby-forum-data = {
source-file = files.blobs."selby-forum-2021-12-14.clean";
2022-03-16 09:49:35 -07:00
target-file = "/run/selby/forum/${data-file}";
user = "root";
2021-12-18 12:10:42 -08:00
};
selby-forum-passwords-sql = {
source-file = "${password-injector-sql files.blobs."forum_selby_ca-passwd.csv"}";
target-file = "/run/postgres/selby/forum-passwords.sql";
user = config.services.postgresql.superUser;
};
};
postgresql = {
databases.${database-name}.users = [ "niten" ];
users.${database-user} = {
password-file = host-secrets.postgresql-selby-discourse-password.target-file;
databases.${database-name} = {
access = "CONNECT,CREATE";
entity-access = {
"ALL TABLES IN SCHEMA public" = "SELECT,INSERT,UPDATE,DELETE";
"ALL SEQUENCES IN SCHEMA public" = "SELECT,UPDATE";
};
};
};
};
};
2022-03-16 09:49:35 -07:00
## Fuckin what why won't this cert work?
services.nginx = {
enable = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
virtualHosts = {
"${site}" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://192.168.55.2:80";
};
};
};
containers.selby-forum = let
parent-host = "192.168.55.1";
container-host = "192.168.55.2";
in {
ephemeral = true;
privateNetwork = true;
localAddress = container-host;
hostAddress = parent-host;
autoStart = true;
bindMounts = {
"/run/selby-discourse" = {
hostPath = "/run/selby/forum";
isReadOnly = true;
};
"/var/lib/discourse" = {
hostPath = state-directory;
isReadOnly = false;
};
};
config = { config, lib, ... }: let
discourse-user = config.systemd.services.discourse.serviceConfig.User;
in {
nixpkgs.pkgs = head-pkgs;
environment.systemPackages = with pkgs; [
nmap
];
networking.firewall.enable = false;
services.discourse = {
enable = true;
hostname = site;
enableACME = false;
plugins = with config.services.discourse.package.plugins; [
discourse-migratepassword
];
admin = {
username = "admin";
fullName = "Admin";
email = "admin@selby.ca";
passwordFile = "/etc/selby-discourse/${admin-pw-file}";
};
database = {
name = database-name;
host = parent-host;
username = database-user;
passwordFile = "/etc/selby-discourse/${db-pw-file}";
};
};
environment.etc = {
"selby-discourse/${admin-pw-file}" = {
source = "/run/selby-discourse/${admin-pw-file}";
user = discourse-user;
mode = "0400";
};
"selby-discourse/${db-pw-file}" = {
source = "/run/selby-discourse/${db-pw-file}";
user = discourse-user;
mode = "0400";
};
"selby-discourse/${data-file}" = {
source = "/run/selby-discourse/${data-file}";
user = discourse-user;
mode = "0400";
};
};
systemd = {
tmpfiles.rules = [
"/run/discourse 750 ${discourse-user} ${discourse-user} - -"
"/var/lib/discourse 750 ${discourse-user} ${discourse-user} - -"
];
services = {
discourse = {
after = [ "multi-user.target" ];
};
discourse-import-vanilla = let
env-without-path =
filterAttrs (attr: _: attr != "PATH")
config.systemd.services.discourse.environment;
selby-forum-data = container-selby-forum-data-file;
in {
description = "One-off job to import Vanilla forum.";
path = config.systemd.services.discourse.path;
environment = env-without-path;
serviceConfig = {
User = config.systemd.services.discourse.serviceConfig.User;
Group = config.systemd.services.discourse.serviceConfig.Group;
Type = "oneshot";
WorkingDirectory = config.systemd.services.discourse.serviceConfig.WorkingDirectory;
ExecStart = pkgs.writeShellScript "import-vanilla-forum.sh" ''
ruby script/import_scripts/vanilla.rb /etc/selby-discourse/${data-file}
'';
};
};
};
};
};
};
2021-12-18 12:10:42 -08:00
systemd = {
tmpfiles.rules = [
2022-03-16 09:49:35 -07:00
"d ${state-directory} 750 - - - -"
2021-12-18 12:10:42 -08:00
];
services = {
discourse-prepare = {
description = "Do discourse's superuser-requiring database work for it.";
2022-03-16 09:49:35 -07:00
wantedBy = [ "container@forum-selby-ca.service" ];
before = [ "container@forum-selby-ca.service" ];
2021-12-18 12:10:42 -08:00
requires = [ config.fudo.postgresql.systemd-target ];
after = [ config.fudo.postgresql.systemd-target ];
path = with pkgs; [ postgresql ];
serviceConfig = {
User = config.services.postgresql.superUser;
ExecStart = pkgs.writeShellScript "discourse-prepare.sh" ''
psql -d ${database-name} -c "CREATE EXTENSION IF NOT EXISTS hstore;"
psql -d ${database-name} -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
'';
};
};
discourse-add-password-hash = let
alter-user-script = pkgs.writeText "create-password-column.sql" ''
2022-03-16 09:49:35 -07:00
ALTER TABLE users ADD COLUMN IF NOT EXISTS import_pass VARCHAR (128);
2021-12-18 12:10:42 -08:00
'';
in {
description = "One-off job to add user password hashes from Vanilla forum.";
path = with pkgs; [ postgresql ];
serviceConfig = {
User = config.services.postgresql.superUser;
Type = "oneshot";
ExecStart = pkgs.writeShellScript "import-vanilla-passwords.sh" ''
psql -d ${database-name} -f ${alter-user-script}
psql -d ${database-name} -f ${host-secrets.selby-forum-passwords-sql.target-file}
'';
};
};
};
};
};
}