277 lines
8.7 KiB
Nix
277 lines
8.7 KiB
Nix
{ 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]}';")
|
|
}
|
|
}
|
|
'';
|
|
|
|
head-pkgs = let
|
|
nixos = pkgs.fetchgit {
|
|
url = "https://github.com/nixos/nixpkgs.git";
|
|
rev = "21.11";
|
|
sha256 = "162dywda2dvfj1248afxc45kcrg83appjd0nmdb541hl7rnncf02";
|
|
};
|
|
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 {
|
|
|
|
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;
|
|
target-file = "/run/selby/forum/${db-pw-file}";
|
|
user = "root";
|
|
};
|
|
|
|
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}";
|
|
target-file = "/run/selby/forum/${admin-pw-file}";
|
|
user = "root";
|
|
};
|
|
|
|
selby-forum-data = {
|
|
source-file = files.blobs."selby-forum-2021-12-14.clean";
|
|
target-file = "/run/selby/forum/${data-file}";
|
|
user = "root";
|
|
};
|
|
|
|
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";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
## 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}
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
systemd = {
|
|
tmpfiles.rules = [
|
|
"d ${state-directory} 750 - - - -"
|
|
];
|
|
|
|
services = {
|
|
discourse-prepare = {
|
|
description = "Do discourse's superuser-requiring database work for it.";
|
|
wantedBy = [ "container@forum-selby-ca.service" ];
|
|
before = [ "container@forum-selby-ca.service" ];
|
|
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" ''
|
|
ALTER TABLE users ADD COLUMN IF NOT EXISTS import_pass VARCHAR (128);
|
|
'';
|
|
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}
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|