diff --git a/flake.nix b/flake.nix
index 5621f25..4fc0dff 100644
--- a/flake.nix
+++ b/flake.nix
@@ -165,8 +165,8 @@
};
# DigitalOcean node
- nixosConfigurations."nki-personal-do" = nixpkgs.lib.nixosSystem rec {
- pkgs = pkgs' system;
+ nixosConfigurations."nki-personal-do" = inputs.nixpkgs-2211.lib.nixosSystem rec {
+ pkgs = pkgs-2211 system;
system = "x86_64-linux";
modules = [
./modules/my-tinc
diff --git a/modules/cloud/writefreely/default.nix b/modules/cloud/writefreely/default.nix
index 3603e92..d6127d5 100644
--- a/modules/cloud/writefreely/default.nix
+++ b/modules/cloud/writefreely/default.nix
@@ -4,8 +4,6 @@ let
cfg = config.cloud.writefreely;
in
{
- imports = [ ./writefreely.nix ];
-
options.cloud.writefreely = {
enable = mkEnableOption "Enable the write.as instance";
package = mkOption {
diff --git a/modules/cloud/writefreely/writefreely.nix b/modules/cloud/writefreely/writefreely.nix
deleted file mode 100644
index 7bd1628..0000000
--- a/modules/cloud/writefreely/writefreely.nix
+++ /dev/null
@@ -1,495 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-let
- inherit (builtins) toString;
- inherit (lib) types mkIf mkOption mkDefault;
- inherit (lib) optional optionals optionalAttrs optionalString;
-
- inherit (pkgs) sqlite;
-
- format = pkgs.formats.ini {
- mkKeyValue = key: value:
- let
- value' =
- if builtins.isNull value then
- ""
- else if builtins.isBool value then
- if value == true then "true" else "false"
- else
- toString value;
- in
- "${key} = ${value'}";
- };
-
- cfg = config.services.writefreely;
-
- isSqlite = cfg.database.type == "sqlite3";
- isMysql = cfg.database.type == "mysql";
- isMysqlLocal = isMysql && cfg.database.createLocally == true;
-
- hostProtocol = if cfg.acme.enable then "https" else "http";
-
- settings = cfg.settings // {
- app = cfg.settings.app or { } // {
- host = cfg.settings.app.host or "${hostProtocol}://${cfg.host}";
- };
-
- database =
- if cfg.database.type == "sqlite3" then {
- type = "sqlite3";
- filename = cfg.settings.database.filename or "writefreely.db";
- database = cfg.database.name;
- } else {
- type = "mysql";
- username = cfg.database.user;
- password = "#dbpass#";
- database = cfg.database.name;
- host = cfg.database.host;
- port = cfg.database.port;
- tls = cfg.database.tls;
- };
-
- server = cfg.settings.server or { } // {
- bind = cfg.settings.server.bind or "localhost";
- gopher_port = cfg.settings.server.gopher_port or 0;
- autocert = !cfg.nginx.enable && cfg.acme.enable;
- templates_parent_dir =
- cfg.settings.server.templates_parent_dir or cfg.package.src;
- static_parent_dir = cfg.settings.server.static_parent_dir or assets;
- pages_parent_dir =
- cfg.settings.server.pages_parent_dir or cfg.package.src;
- keys_parent_dir = cfg.settings.server.keys_parent_dir or cfg.stateDir;
- };
- };
-
- configFile = format.generate "config.ini" settings;
-
- assets = pkgs.stdenvNoCC.mkDerivation {
- pname = "writefreely-assets";
-
- inherit (cfg.package) version src;
-
- nativeBuildInputs = with pkgs.nodePackages; [ less ];
-
- buildPhase = ''
- mkdir -p $out
-
- cp -r static $out/
- '';
-
- installPhase = ''
- less_dir=$src/less
- css_dir=$out/static/css
-
- lessc $less_dir/app.less $css_dir/write.css
- lessc $less_dir/fonts.less $css_dir/fonts.css
- lessc $less_dir/icons.less $css_dir/icons.css
- lessc $less_dir/prose.less $css_dir/prose.css
- '';
- };
-
- withConfigFile = text: ''
- db_pass=${
- optionalString (cfg.database.passwordFile != null)
- "$(head -n1 ${cfg.database.passwordFile})"
- }
-
- cp -f ${configFile} '${cfg.stateDir}/config.ini'
- sed -e "s,#dbpass#,$db_pass,g" -i '${cfg.stateDir}/config.ini'
- chmod 440 '${cfg.stateDir}/config.ini'
-
- ${text}
- '';
-
- withMysql = text:
- withConfigFile ''
- query () {
- local result=$(${config.services.mysql.package}/bin/mysql \
- --user=${cfg.database.user} \
- --password=$db_pass \
- --database=${cfg.database.name} \
- --silent \
- --raw \
- --skip-column-names \
- --execute "$1" \
- )
-
- echo $result
- }
-
- ${text}
- '';
-
- withSqlite = text:
- withConfigFile ''
- query () {
- local result=$(${sqlite}/bin/sqlite3 \
- '${cfg.stateDir}/${settings.database.filename}'
- "$1" \
- )
-
- echo $result
- }
-
- ${text}
- '';
-in
-{
- options.services.writefreely = {
- enable =
- lib.mkEnableOption "Writefreely, build a digital writing community";
-
- package = lib.mkOption {
- type = lib.types.package;
- default = pkgs.writefreely;
- defaultText = lib.literalExpression "pkgs.writefreely";
- description = "Writefreely package to use.";
- };
-
- stateDir = mkOption {
- type = types.path;
- default = "/var/lib/writefreely";
- description = "The state directory where keys and data are stored.";
- };
-
- user = mkOption {
- type = types.str;
- default = "writefreely";
- description = "User under which Writefreely is ran.";
- };
-
- group = mkOption {
- type = types.str;
- default = "writefreely";
- description = "Group under which Writefreely is ran.";
- };
-
- host = mkOption {
- type = types.str;
- default = "";
- description = "The public host name to serve.";
- example = "example.com";
- };
-
- settings = mkOption {
- default = { };
- description = ''
- Writefreely configuration (config.ini). Refer to
-
- for details.
- '';
-
- type = types.submodule {
- freeformType = format.type;
-
- options = {
- app = {
- theme = mkOption {
- type = types.str;
- default = "write";
- description = "The theme to apply.";
- };
- };
-
- server = {
- port = mkOption {
- type = types.port;
- default = if cfg.nginx.enable then 18080 else 80;
- defaultText = "80";
- description = "The port WriteFreely should listen on.";
- };
- };
- };
- };
- };
-
- database = {
- type = mkOption {
- type = types.enum [ "sqlite3" "mysql" ];
- default = "sqlite3";
- description = "The database provider to use.";
- };
-
- name = mkOption {
- type = types.str;
- default = "writefreely";
- description = "The name of the database to store data in.";
- };
-
- user = mkOption {
- type = types.nullOr types.str;
- default = if cfg.database.type == "mysql" then "writefreely" else null;
- defaultText = "writefreely";
- description = "The database user to connect as.";
- };
-
- passwordFile = mkOption {
- type = types.nullOr types.path;
- default = null;
- description = "The file to load the database password from.";
- };
-
- host = mkOption {
- type = types.str;
- default = "localhost";
- description = "The database host to connect to.";
- };
-
- port = mkOption {
- type = types.port;
- default = 3306;
- description = "The port used when connecting to the database host.";
- };
-
- tls = mkOption {
- type = types.bool;
- default = false;
- description =
- "Whether or not TLS should be used for the database connection.";
- };
-
- migrate = mkOption {
- type = types.bool;
- default = true;
- description =
- "Whether or not to automatically run migrations on startup.";
- };
-
- createLocally = mkOption {
- type = types.bool;
- default = false;
- description = ''
- When is set to
- "mysql"
, this option will enable the MySQL service locally.
- '';
- };
- };
-
- admin = {
- name = mkOption {
- type = types.nullOr types.str;
- description = "The name of the first admin user.";
- default = null;
- };
-
- initialPasswordFile = mkOption {
- type = types.path;
- description = ''
- Path to a file containing the initial password for the admin user.
- If not provided, the default password will be set to nixos
.
- '';
- default = pkgs.writeText "default-admin-pass" "nixos";
- defaultText = "/nix/store/xxx-default-admin-pass";
- };
- };
-
- nginx = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description =
- "Whether or not to enable and configure nginx as a proxy for WriteFreely.";
- };
-
- forceSSL = mkOption {
- type = types.bool;
- default = false;
- description = "Whether or not to force the use of SSL.";
- };
- };
-
- acme = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description =
- "Whether or not to automatically fetch and configure SSL certs.";
- };
- };
- };
-
- config = mkIf cfg.enable {
- assertions = [
- {
- assertion = cfg.host != "";
- message = "services.writefreely.host must be set";
- }
- {
- assertion = isMysqlLocal -> cfg.database.passwordFile != null;
- message =
- "services.writefreely.database.passwordFile must be set if services.writefreely.database.createLocally is set to true";
- }
- {
- assertion = isSqlite -> !cfg.database.createLocally;
- message =
- "services.writefreely.database.createLocally has no use when services.writefreely.database.type is set to sqlite3";
- }
- ];
-
- users = {
- users = optionalAttrs (cfg.user == "writefreely") {
- writefreely = {
- group = cfg.group;
- home = cfg.stateDir;
- isSystemUser = true;
- };
- };
-
- groups =
- optionalAttrs (cfg.group == "writefreely") { writefreely = { }; };
- };
-
- systemd.tmpfiles.rules =
- [ "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" ];
-
- systemd.services.writefreely = {
- after = [ "network.target" ]
- ++ optional isSqlite "writefreely-sqlite-init.service"
- ++ optional isMysql "writefreely-mysql-init.service"
- ++ optional isMysqlLocal "mysql.service";
- wantedBy = [ "multi-user.target" ];
-
- path = with pkgs; [ openssl ];
-
- serviceConfig = {
- Type = "simple";
- User = cfg.user;
- Group = cfg.group;
- WorkingDirectory = cfg.stateDir;
- Restart = "always";
- RestartSec = 20;
- ExecStart =
- "${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' serve";
- AmbientCapabilities =
- optionalString (settings.server.port < 1024) "cap_net_bind_service";
- };
-
- preStart = ''
- if ! test -d "${cfg.stateDir}/keys"; then
- mkdir -p ${cfg.stateDir}/keys
-
- # Key files end up with the wrong permissions by default.
- # We need to correct them so that Writefreely can read them.
- chmod -R 750 "${cfg.stateDir}/keys"
-
- ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' keys generate
- fi
- '';
- };
-
- systemd.services.writefreely-sqlite-init = mkIf isSqlite {
- wantedBy = [ "multi-user.target" ];
-
- serviceConfig = {
- Type = "oneshot";
- User = cfg.user;
- Group = cfg.group;
- WorkingDirectory = cfg.stateDir;
- ReadOnlyPaths = optional (cfg.admin.initialPasswordFile != null)
- cfg.admin.initialPasswordFile;
- };
-
- script =
- let
- migrateDatabase = optionalString cfg.database.migrate ''
- ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate
- '';
-
- createAdmin = optionalString (cfg.admin.name != null) ''
- if [[ $(query "SELECT COUNT(*) FROM users") == 0 ]]; then
- admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile})
-
- ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass
- fi
- '';
- in
- withSqlite ''
- if ! test -f '${settings.database.filename}'; then
- ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init
- fi
-
- ${migrateDatabase}
-
- ${createAdmin}
- '';
- };
-
- systemd.services.writefreely-mysql-init = mkIf isMysql {
- wantedBy = [ "multi-user.target" ];
- after = optional isMysqlLocal "mysql.service";
-
- serviceConfig = {
- Type = "oneshot";
- User = cfg.user;
- Group = cfg.group;
- WorkingDirectory = cfg.stateDir;
- ReadOnlyPaths = optional isMysqlLocal cfg.database.passwordFile
- ++ optional (cfg.admin.initialPasswordFile != null)
- cfg.admin.initialPasswordFile;
- };
-
- script =
- let
- updateUser = optionalString isMysqlLocal ''
- # WriteFreely currently *requires* a password for authentication, so we
- # need to update the user in MySQL accordingly. By default MySQL users
- # authenticate with auth_socket or unix_socket.
- # See: https://github.com/writefreely/writefreely/issues/568
- ${config.services.mysql.package}/bin/mysql --skip-column-names --execute "ALTER USER '${cfg.database.user}'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('$db_pass'); FLUSH PRIVILEGES;"
- '';
-
- migrateDatabase = optionalString cfg.database.migrate ''
- ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate
- '';
-
- createAdmin = optionalString (cfg.admin.name != null) ''
- if [[ $(query 'SELECT COUNT(*) FROM users') == 0 ]]; then
- admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile})
- ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass
- fi
- '';
- in
- withMysql ''
- ${updateUser}
-
- if [[ $(query "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '${cfg.database.name}'") == 0 ]]; then
- ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init
- fi
-
- ${migrateDatabase}
-
- ${createAdmin}
- '';
- };
-
- services.mysql = mkIf isMysqlLocal {
- enable = true;
- package = mkDefault pkgs.mariadb;
- ensureDatabases = [ cfg.database.name ];
- ensureUsers = [{
- name = cfg.database.user;
- ensurePermissions = {
- "${cfg.database.name}.*" = "ALL PRIVILEGES";
- # WriteFreely requires the use of passwords, so we need permissions
- # to `ALTER` the user to add password support and also to reload
- # permissions so they can be used.
- "*.*" = "CREATE USER, RELOAD";
- };
- }];
- };
-
- services.nginx = lib.mkIf cfg.nginx.enable {
- enable = true;
- recommendedProxySettings = true;
-
- virtualHosts."${cfg.host}" = {
- enableACME = cfg.acme.enable;
- forceSSL = cfg.nginx.forceSSL;
-
- locations."/" = {
- proxyPass = "http://127.0.0.1:${toString settings.server.port}";
- };
- };
- };
- };
-}