diff --git a/.gitignore b/.gitignore
index 36de04e..e51ba08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,13 @@
!hosts/
+!hosts/cube/
+!hosts/cube/matrix/
+!hosts/cube/nextcloud/
+!hosts/cube/nextcloud/*.gif
+!hosts/cube/grafana/
+!hosts/cube/forgejo/
+
!hosts/disk/
!hosts/nine/
diff --git a/hosts/cube/default.nix b/hosts/cube/default.nix
new file mode 100644
index 0000000..184887e
--- /dev/null
+++ b/hosts/cube/default.nix
@@ -0,0 +1,73 @@
+lib: lib.nixosSystem ({ config, keys, lib, ... }: let
+ inherit (lib) collectNix remove;
+in {
+ imports = collectNix ./. |> remove ./default.nix;
+
+ secrets.id.file = ./id.age;
+ services.openssh.hostKeys = [{
+ type = "ed25519";
+ path = config.secrets.id.path;
+ }];
+
+ services.openssh.banner = ''
+ _______________________________________
+ / If God doesn't destroy San Francisco, \
+ | He should apologize to Sodom and |
+ \ Gomorrah. /
+ ---------------------------------------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+ '';
+
+ secrets.rgbPassword.file = ./password.rgb.age;
+ users.users = {
+ root.hashedPasswordFile = config.secrets.rgbPassword.path;
+
+ rgb = {
+ description = "RGB";
+ openssh.authorizedKeys.keys = keys.admins;
+ hashedPasswordFile = config.secrets.rgbPassword.path;
+ isNormalUser = true;
+ extraGroups = [ "wheel" ];
+ };
+
+ backup = {
+ description = "Backup";
+ openssh.authorizedKeys.keys = keys.all;
+ hashedPasswordFile = config.secrets.rgbPassword.path;
+ isNormalUser = true;
+ };
+ };
+
+ home-manager.users = {
+ root = {};
+ rgb = {};
+ backup = {};
+ };
+
+ networking = let
+ interface = "ens18";
+ in {
+ hostName = "cube";
+
+ ipv4.address = "5.255.78.70";
+ ipv4.prefixLength = 24;
+
+ domain = "rgbcu.be";
+
+ defaultGateway = {
+ inherit interface;
+
+ address = "5.255.78.1";
+ };
+ };
+
+ nixpkgs.hostPlatform = "x86_64-linux";
+ system.stateVersion = "23.05";
+ home-manager.sharedModules = [{
+ home.stateVersion = "23.11";
+ }];
+})
diff --git a/hosts/cube/forgejo/default.nix b/hosts/cube/forgejo/default.nix
new file mode 100644
index 0000000..c8dabdf
--- /dev/null
+++ b/hosts/cube/forgejo/default.nix
@@ -0,0 +1,161 @@
+{ self, config, lib, pkgs, ... }: let
+ inherit (config.networking) domain;
+ inherit (lib) const enabled genAttrs head merge mkForce;
+
+ fqdn = "git.${domain}";
+
+ port = 8001;
+in {
+ secrets.forgejoPasswordRunner = {
+ file = ./password.runner.age;
+ owner = "forgejo";
+ };
+ secrets.forgejoPasswordMail = {
+ file = self + /modules/mail/password.plain.age;
+ owner = "forgejo";
+ };
+
+ services.postgresql = let
+ users = [ "forgejo" ];
+ in {
+ ensureDatabases = users;
+ ensureUsers = map users (name: {
+ inherit name;
+
+ ensureDBOwnership = true;
+ });
+ };
+
+ services.restic.backups = genAttrs config.services.restic.hosts <| const {
+ paths = [ "/var/lib/gitea-runner" "/var/lib/forgejo" ];
+ };
+
+ users.groups.gitea-runner = {};
+ users.users.gitea-runner = {
+ extraGroups = [ "docker" ];
+ group = "gitea-runner";
+ home = "/var/lib/gitea-runner";
+ isSystemUser = true;
+ };
+
+ services.gitea-actions-runner = {
+ package = pkgs.forgejo-actions-runner;
+
+ instances.runner-01 = enabled {
+ name = "runner-01";
+ url = fqdn;
+
+ labels = [
+ "debian-latest:docker://node:18-bullseye"
+ "ubuntu-latest:docker://node:18-bullseye"
+ "act:docker://ghcr.io/catthehacker/ubuntu:act-latest"
+ ];
+
+ tokenFile = config.secrets.forgejoPasswordRunner.path;
+
+ settings = {
+ cache.enabled = true;
+ capacity = 4;
+ container.network = "host";
+ };
+
+ hostPackages = [
+ pkgs.bash
+ pkgs.uutils-coreutils-noprefix
+ pkgs.curl
+ pkgs.gitMinimal
+ pkgs.sudo
+ pkgs.wget
+ ];
+ };
+ };
+
+ services.openssh.settings.AcceptEnv = mkForce "SHELLS COLOTERM GIT_PROTOCOL";
+
+ services.forgejo = enabled {
+ lfs = enabled;
+
+ secrets.mailer.PASSWD = config.secrets.forgejoPasswordMail.path;
+
+ database = {
+ socket = "/run/postgresql";
+ type = "postgres";
+ };
+
+ settings = let
+ description = "RGBCube's Forge of Shitty Software";
+ in {
+ default.APP_NAME = description;
+
+ actions = {
+ ENABLED = true;
+ DEFAULT_ACTIONS_URL = "https://${fqdn}";
+ };
+
+ attachment.ALLOWED_TYPES = "*/*";
+
+ cache.ENABLED = true;
+
+ mailer = {
+ ENABLED = true;
+
+ PROTOCOL = "smtps";
+ SMTP_ADDR = self.disk.mailserver.fqdn;
+ USER = "git@${domain}";
+ };
+
+ other = {
+ SHOW_FOOTER_TEMPLATE_LOAD_TIME = false;
+ SHOW_FOOTER_VERSION = false;
+ };
+
+ packages.ENABLED = false;
+
+ repository = {
+ DEFAULT_BRANCH = "master";
+ DEFAULT_MERGE_STYLE = "rebase-merge";
+ DEFAULT_REPO_UNITS = "repo.code, repo.issues, repo.pulls, repo.actions";
+
+ DEFAULT_PUSH_CREATE_PRIVATE = false;
+ ENABLE_PUSH_CREATE_ORG = true;
+ ENABLE_PUSH_CREATE_USER = true;
+
+ DISABLE_STARS = true;
+ };
+
+ "repository.upload" = {
+ FILE_MAX_SIZE = 100;
+ MAX_FILES = 10;
+ };
+
+ server = {
+ DOMAIN = domain;
+ ROOT_URL = "https://${fqdn}/";
+ LANDING_PAGE = "/explore";
+
+ HTTP_ADDR = "::1";
+ HTTP_PORT = port;
+
+ SSH_PORT = head config.services.openssh.ports;
+
+ DISABLE_ROUTER_LOG = true;
+ };
+
+ service.DISABLE_REGISTRATION = true;
+
+ session = {
+ COOKIE_SECURE = true;
+ SAME_SITE = "strict";
+ };
+
+ "ui.meta" = {
+ AUTHOR = description;
+ DESCRIPTION = description;
+ };
+ };
+ };
+
+ services.nginx.virtualHosts.${fqdn} = merge config.nginx.sslTemplate {
+ locations."/".proxyPass = "http://[::1]:${toString port}";
+ };
+}
diff --git a/hosts/cube/forgejo/password.runner.age b/hosts/cube/forgejo/password.runner.age
new file mode 100644
index 0000000..8d48852
--- /dev/null
+++ b/hosts/cube/forgejo/password.runner.age
@@ -0,0 +1,8 @@
+age-encryption.org/v1
+-> ssh-ed25519 +rZ0Tw w2DgM8xAXzEYvEPHwf2SKgG6UThGCsC9O5GJtBEmESA
+ID5KL9YemWr93wy66VQzgzoidMSR9TQKZYgNJp6WAoc
+-> ssh-ed25519 CzqbPQ U1lCAlt/cyCwbo4VaEv7edcwGdEGzdHRSoDjvYyWkxI
+JWVcb5a3iNeJv75AHNHr/9nU6pE6SnmS/5N+oZbl/cg
+--- qBV+LTrheqYtuHtzeDpZTPa96P1Q91wcf7pMcIKBzFM
+5=ghS+aߪċݍ_YeE
+iB5UWo"JZ#(r`LZV
\ No newline at end of file
diff --git a/hosts/cube/grafana/default.nix b/hosts/cube/grafana/default.nix
new file mode 100644
index 0000000..f3ff58e
--- /dev/null
+++ b/hosts/cube/grafana/default.nix
@@ -0,0 +1,86 @@
+{ self, config, lib, ... }: let
+ inherit (config.networking) domain;
+ inherit (lib) const enabled genAttrs merge;
+
+ fqdn = "metrics.${domain}";
+
+ port = 8000;
+in {
+ secrets.grafanaPassword = {
+ file = ./password.age;
+ owner = "grafana";
+ };
+ secrets.grafanaPasswordMail = {
+ file = self + /modules/mail/password.plain.age;
+ owner = "grafana";
+ };
+
+ services.postgresql = let
+ users = [ "grafana" ];
+ in {
+ ensureDatabases = users;
+ ensureUsers = map users (name: {
+ inherit name;
+
+ ensureDBOwnership = true;
+ });
+ };
+
+ services.restic.backups = genAttrs config.services.restic.hosts <| const {
+ paths = [ "/var/lib/grafana" ];
+ };
+
+ systemd.services.grafana = {
+ after = [ "postgresql.service" ];
+ requires = [ "postgresql.service" ];
+ };
+
+ services.grafana = enabled {
+ provision = enabled;
+
+ settings = {
+ analytics.reporting_enabled = false;
+
+ database.host = "/run/postgresql";
+ database.type = "postgres";
+ database.user = "grafana";
+
+ server.domain = fqdn;
+ server.http_addr = "[::1]";
+ server.http_port = port;
+
+ users.default_theme = "system";
+ };
+
+ settings.security = {
+ admin_email = "metrics@${domain}";
+ admin_password = "$__file{${config.secrets.grafanaPassword.path}}";
+ admin_user = "admin";
+
+ cookie_secure = true;
+ disable_gravatar = true;
+
+ disable_initial_admin_creation = true; # Just in case.
+ };
+
+ settings.smtp = {
+ enabled = true;
+
+ password = "$__file{${config.secrets.grafanaPasswordMail.path}}";
+ startTLS_policy = "MandatoryStartTLS";
+
+ ehlo_identity = "metrics@${domain}";
+ from_address = "metrics@${domain}";
+ from_name = "Metrics";
+ host = "${self.disk.mailserver.fqdn}:${toString self.disk.services.postfix.relayPort}";
+ };
+ };
+
+ services.nginx.virtualHosts.${fqdn} = merge config.nginx.sslTemplate {
+ locations."/" = {
+ proxyPass = "http://[::1]:${toString port}";
+ proxyWebsockets = true;
+ };
+ };
+}
+
diff --git a/hosts/cube/grafana/password.age b/hosts/cube/grafana/password.age
new file mode 100644
index 0000000..5085c24
Binary files /dev/null and b/hosts/cube/grafana/password.age differ
diff --git a/hosts/cube/hardware.nix b/hosts/cube/hardware.nix
new file mode 100644
index 0000000..5984ea7
--- /dev/null
+++ b/hosts/cube/hardware.nix
@@ -0,0 +1,23 @@
+{ lib, modulesPath, ... }: let
+ inherit (lib) enabled;
+in {
+ imports = [(modulesPath + "/profiles/qemu-guest.nix")];
+
+ boot.loader.grub = enabled {
+ device = "/dev/vda";
+ };
+
+ boot.initrd.availableKernelModules = [
+ "ata_piix"
+ "sr_mod"
+ "uhci_hcd"
+ "virtio_blk"
+ "virtio_pci"
+ ];
+
+ fileSystems."/" = {
+ device = "/dev/disk/by-label/root";
+ fsType = "ext4";
+ options = [ "noatime" ];
+ };
+}
diff --git a/hosts/cube/id.age b/hosts/cube/id.age
new file mode 100644
index 0000000..524f542
Binary files /dev/null and b/hosts/cube/id.age differ
diff --git a/hosts/cube/matrix/default.nix b/hosts/cube/matrix/default.nix
new file mode 100644
index 0000000..59174c1
--- /dev/null
+++ b/hosts/cube/matrix/default.nix
@@ -0,0 +1,136 @@
+{ config, lib, ... }: let
+ inherit (config.networking) domain;
+ inherit (lib) const enabled genAttrs merge strings;
+
+ pathSite = "/var/www/site";
+
+ domainChat = "chat.${domain}";
+ domainSync = "sync.${domain}";
+
+ wellKnownResponse = data: ''
+ default_type application/json;
+ add_header Access-Control-Allow-Origin *;
+ return 200 '${strings.toJSON data}';
+ '';
+
+ configClient."m.homeserver".base_url = "https://${domainChat}";
+ configClient."org.matrix.msc3575.proxy".url = "https://${domainSync}";
+
+ configServer."m.server" = "${domainChat}:443";
+
+ configWellKnownResponse.locations = {
+ "= /.well-known/matrix/client".extraConfig = wellKnownResponse configClient;
+ "= /.well-known/matrix/server".extraConfig = wellKnownResponse configServer;
+ };
+
+ configNotFoundLocation = {
+ locations."/".extraConfig = "return 404;";
+
+ extraConfig = "error_page 404 /404.html;";
+ locations."/404".extraConfig = "internal;";
+
+ locations."/assets/".extraConfig = "return 301 https://${domain}$request_uri;";
+ };
+
+ portSynapse = 8002;
+ portSync = 8003;
+in {
+ secrets.matrixSecret = {
+ file = ./password.secret.age;
+ owner = "matrix-synapse";
+ };
+ secrets.matrixSyncPassword = {
+ file = ./password.sync.age;
+ owner = "matrix-synapse";
+ };
+
+ services.postgresql = let
+ users = [ "matrix-synapse" "matrix-sliding-sync" ];
+ in {
+ ensureDatabases = users;
+ ensureUsers = map users (name: {
+ inherit name;
+
+ ensureDBOwnership = true;
+ });
+ };
+
+ services.restic.backups = genAttrs config.services.restic.hosts <| const {
+ paths = [ "/var/lib/matrix-synapse" "/var/lib/matrix-sliding-sync" ];
+ };
+
+ services.matrix-synapse = enabled {
+ withJemalloc = true;
+
+ configureRedisLocally = true;
+ settings.redis.enabled = true;
+
+ extras = [ "postgres" "url-preview" "user-search" ];
+
+ log.root.level = "WARNING"; # Shut the fuck up.
+
+ settings = {
+ server_name = domain;
+ # We are not setting web_client_location since the root is not accessible
+ # from the outside web at all. Only /_matrix is reverse proxied to.
+
+ database.name = "psycopg2";
+
+ report_stats = false;
+
+ enable_metrics = true;
+ metrics_flags.known_servers = true;
+
+ expire_access_token = true;
+ url_preview_enabled = true;
+
+ # Trusting Matrix.org.
+ suppress_key_server_warning = true;
+ };
+
+ # Sets registration_shared_secret.
+ extraConfigFiles = [ config.secrets.matrixSecret.path ];
+
+ settings.listeners = [{
+ port = portSynapse;
+
+ bind_addresses = [ "::1" ];
+ tls = false;
+ type = "http";
+ x_forwarded = true;
+
+ resources = [{
+ compress = false;
+ names = [ "client" "federation" ];
+ }];
+ }];
+ };
+
+ services.nginx.virtualHosts.${domain} = configWellKnownResponse;
+
+ services.nginx.virtualHosts.${domainChat} = merge config.nginx.sslTemplate configWellKnownResponse configNotFoundLocation {
+ root = "${pathSite}";
+
+ locations."/_matrix".proxyPass = "http://[::1]:${toString portSynapse}";
+ locations."/_synapse/client".proxyPass = "http://[::1]:${toString portSynapse}";
+ };
+
+ services.matrix-sliding-sync = enabled {
+ environmentFile = config.age.secrets.matrixSyncPassword.path;
+ settings = {
+ SYNCV3_SERVER = "https://${domainChat}";
+ SYNCV3_DB = "postgresql:///matrix-sliding-sync?host=/run/postgresql";
+ SYNCV3_BINDADDR = "[::1]:${toString portSync}";
+ };
+ };
+
+ services.nginx.virtualHosts.${domainSync} = merge config.nginx.sslTemplate configNotFoundLocation {
+ root = pathSite;
+
+ locations."~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync)"
+ .proxyPass = "http://[::1]:${toString portSynapse}";
+
+ locations."~ ^(\\/_matrix|\\/_synapse\\/client)"
+ .proxyPass = "http://[::1]:${toString portSync}";
+ };
+}
diff --git a/hosts/cube/matrix/password.secret.age b/hosts/cube/matrix/password.secret.age
new file mode 100644
index 0000000..220b2f8
--- /dev/null
+++ b/hosts/cube/matrix/password.secret.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 +rZ0Tw JrLJgFemnQUQpZ+SYnEs0gVfPYmLyVM0ibPzLa9UKU0
+rZ9DtsOexcUGuPc4Rlfj9u0cbqU4z5R4M9MuKPyL/Zk
+-> ssh-ed25519 CzqbPQ 5NibbW1CERCv8QTAuz5zeKxue1j23FyvQJn1ppjkXWg
+oN12GPJsxJzRMrzUp34oLO0SvwT+Ed8CLCRqCtU0LrY
+--- Y+OUAHyQ0irtOVcLDx1WvyIwp5VdkM2wqqhmeCMok6A
+\{Z_?q74X˦+d^$4`B3(^Ri)$WѭyX=-"<$X$:@̴XHXgq
ʤO v <[o&CUkW|e_̺
\ No newline at end of file
diff --git a/hosts/cube/matrix/password.sync.age b/hosts/cube/matrix/password.sync.age
new file mode 100644
index 0000000..bf794d3
--- /dev/null
+++ b/hosts/cube/matrix/password.sync.age
@@ -0,0 +1,8 @@
+age-encryption.org/v1
+-> ssh-ed25519 +rZ0Tw txU8aL7ixRa9bTrV+FR5Vs8UrZ/JCNNblezCm/NJLWE
+9ucwZW0qvCAc5EilV1B9XC+OA5Ro3FS6KBLGKT6NArI
+-> ssh-ed25519 CzqbPQ 5DDlTXg4RIYcTcusedLRkuK3dbtccfQ0HiVFUH5B5XQ
+6dW9qE5UMpOSohXIu559wBnPnOrTG/mqtrWvsy5CqYw
+--- UO+CkdYt44UO16Yv3+sCJ5IoM2D+Pus7jEPbRFwGyKU
+bsX
+Pt \Twݟq{:l9%(Bd]hǹ|SMQ}^/qu]oXE@"ܑݟ|H}\pmd
\ No newline at end of file
diff --git a/hosts/cube/nextcloud/default.nix b/hosts/cube/nextcloud/default.nix
new file mode 100644
index 0000000..158b11a
--- /dev/null
+++ b/hosts/cube/nextcloud/default.nix
@@ -0,0 +1,118 @@
+ { config, lib, pkgs, ... }: let
+ inherit (config.networking) domain;
+ inherit (lib) const enabled genAttrs mkAfter;
+
+ fqdn = "cloud.${domain}";
+
+ packageNextcloud = pkgs.nextcloud29;
+in {
+ secrets.nextcloudPassword = {
+ file = ./password.age;
+ owner = "nextcloud";
+ };
+ secrets.nextcloudPasswordExporter = {
+ file = ./password.age;
+ owner = "nextcloud-exporter";
+ };
+
+ services.prometheus.exporters.nextcloud = enabled {
+ listenAddress = "[::]";
+
+ username = "admin";
+ url = "https://${fqdn}";
+ passwordFile = config.secrets.nextcloudPasswordExporter.path;
+ };
+
+ services.postgresql = let
+ users = [ "nextcloud" ];
+ in {
+ ensureDatabases = users;
+ ensureUsers = map users (name: {
+ inherit name;
+
+ ensureDBOwnership = true;
+ });
+ };
+
+ services.restic.backups = genAttrs config.services.restic.hosts <| const {
+ paths = [ "/var/lib/nextcloud" ];
+ };
+
+ systemd.services.nextcloud-setup = {
+ after = [ "postgresql.service" ];
+ requires = [ "postgresql.service" ];
+
+ script = mkAfter ''
+ nextcloud-occ theming:config name "RGBCube's Depot"
+ nextcloud-occ theming:config slogan "RGBCube's storage of insignificant data."
+
+ nextcloud-occ theming:config color "#000000"
+ nextcloud-occ theming:config background backgroundColor
+
+ nextcloud-occ theming:config logo ${./icon.gif}
+ '';
+ };
+
+ services.nextcloud = enabled {
+ package = packageNextcloud;
+
+ hostName = fqdn;
+ https = true;
+
+ configureRedis = true;
+
+ config.adminuser = "admin";
+ config.adminpassFile = config.secrets.nextcloudPassword.path;
+
+ config.dbhost = "/run/postgresql";
+ config.dbtype = "pgsql";
+
+ settings = {
+ default_phone_region = "TR";
+
+ # Even with manual SMTP configuration, Nextcloud fails to communicate properly
+ # and fails to send mail. PHP moment?
+ # mail_smtphost = "::1"; # FIXME: Will need to use SMTP.
+ # mail_smtpmode = "sendmail";
+ # mail_from_address = "cloud";
+
+ maintenance_window_start = 1;
+
+ # No clue why it was syslog.
+ # What are the NixOS module authors on?
+ log_type = "file";
+ };
+
+ settings.enabledPreviewProviders = [
+ "OC\\Preview\\BMP"
+ "OC\\Preview\\GIF"
+ "OC\\Preview\\JPEG"
+ "OC\\Preview\\Krita"
+ "OC\\Preview\\MarkDown"
+ "OC\\Preview\\MP3"
+ "OC\\Preview\\OpenDocument"
+ "OC\\Preview\\PNG"
+ "OC\\Preview\\TXT"
+ "OC\\Preview\\XBitmap"
+ "OC\\Preview\\HEIC"
+ ];
+
+ phpOptions = {
+ "opcache.interned_strings_buffer" = "16";
+ output_buffering = "off";
+ };
+
+ extraAppsEnable = true;
+ extraApps = {
+ inherit (packageNextcloud.packages.apps)
+ bookmarks calendar contacts deck
+ forms impersonate mail # groupfolders impersonate mail
+ maps notes polls previewgenerator; # tasks;
+ # Add: files_markdown files_texteditor memories news
+ };
+
+ nginx.recommendedHttpHeaders = true;
+ };
+
+ services.nginx.virtualHosts.${fqdn} = config.ngnixSslTemplate;
+}
diff --git a/hosts/cube/nextcloud/icon.gif b/hosts/cube/nextcloud/icon.gif
new file mode 100644
index 0000000..7449097
Binary files /dev/null and b/hosts/cube/nextcloud/icon.gif differ
diff --git a/hosts/cube/nextcloud/password.age b/hosts/cube/nextcloud/password.age
new file mode 100644
index 0000000..51bd118
--- /dev/null
+++ b/hosts/cube/nextcloud/password.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 +rZ0Tw B5yow6s83Ij7ymJ4DVisL/Q58+tewqii8SLknj+WDCI
+lkD9VftG4FA8sIztdrlCfaiaaSiKIEThT8gvGPuYvto
+-> ssh-ed25519 CzqbPQ eHxowar9M2Zw7DheC9Cj2jwtCFKuPHJiNTGNtJOc2Ek
+2LMp4JqjbKbW1Sglf06h7ZtPTA0+qxNj8QJbz7drH1k
+--- kCW5Y/0JPRigRjj3CNpr4ruLsG1f5tBXoEX1eVKjB7Q
+MpX1&rCx 3N5ޑ65>W9W
\ No newline at end of file
diff --git a/hosts/cube/password.rgb.age b/hosts/cube/password.rgb.age
new file mode 100644
index 0000000..ae896ef
Binary files /dev/null and b/hosts/cube/password.rgb.age differ
diff --git a/hosts/cube/podman.nix b/hosts/cube/podman.nix
new file mode 100644
index 0000000..a798fbc
--- /dev/null
+++ b/hosts/cube/podman.nix
@@ -0,0 +1,15 @@
+{ lib, ... }: let
+ inherit (lib) enabled;
+in {
+ virtualisation.podman = enabled {
+ dockerCompat = true;
+ dockerSocket = enabled;
+
+ defaultNetwork.settings.dns_enabled = true;
+
+ autoPrune = enabled {
+ dates = "weekly";
+ flags = [ "--all" ];
+ };
+ };
+}
diff --git a/hosts/cube/postgresql.nix b/hosts/cube/postgresql.nix
new file mode 100644
index 0000000..1b39eef
--- /dev/null
+++ b/hosts/cube/postgresql.nix
@@ -0,0 +1,114 @@
+{ config, lib, pkgs, ... }: let
+ inherit (lib) const enabled genAttrs mkForce mkOverride;
+in {
+ environment.systemPackages = [
+ config.services.postgresql.package
+ ];
+
+ services.prometheus.exporters.postgres = enabled {
+ listenAddress = "[::]";
+ runAsLocalSuperUser = true;
+ };
+
+ services.restic.backups = genAttrs config.services.restic.hosts <| const {
+ paths = [ "/tmp/postgresql-dump.sql.gz" ];
+
+ backupPrepareCommand = ''
+ ${config.services.postgresql.package}/bin/pg_dumpall --clean \
+ | ${lib.getExe pkgs.gzip} --rsyncable \
+ > /tmp/postgresql-dump.sql.gz
+ '';
+
+ backupCleanupCommand = ''
+ rm /tmp/postgresql-dump.sql.gz
+ '';
+ };
+
+ services.postgresql = enabled {
+ package = pkgs.postgresql_14;
+
+ enableJIT = true;
+
+ initdbArgs = [ "--locale=C" "--encoding=UTF8" ];
+ initialScript = pkgs.writeText "grant-root-perms" ''
+ GRANT pg_read_all_data TO root;
+ GRANT pg_write_all_data TO root;
+ '';
+
+ authentication = mkOverride 10 ''
+ # Type Database DBUser Authentication
+ local all all peer
+ '';
+
+ ensureUsers = map [ "postgres" "root" ] (name: {
+ inherit name;
+
+ ensureClauses = {
+ createdb = true;
+ createrole = true;
+ login = true;
+ replication = true;
+ superuser = true;
+ };
+ });
+
+ settings = {
+ listen_addresses = mkForce "";
+
+ # Generated by
+ max_connections = 100;
+ superuser_reserved_connections = 3;
+
+ # Memory Settings
+ shared_buffers = "1024 MB";
+ work_mem = "32 MB";
+ maintenance_work_mem = "320 MB";
+ huge_pages = "off";
+ effective_cache_size = "3 GB";
+ effective_io_concurrency = 1; # Concurrent IO only really activated if OS supports posix_fadvise function.
+ random_page_cost = 4; # Speed of random disk access relative to sequential access (1.0).
+
+ # Monitoring
+ shared_preload_libraries = "pg_stat_statements"; # Per statement resource usage stats.
+ track_io_timing = "on"; # Measure exact block IO times.
+ track_functions = "pl"; # Track execution times of pl-language procedures if any.
+
+ # Replication
+ wal_level = "replica";
+ max_wal_senders = 0;
+ synchronous_commit = "on";
+
+ # Checkpointing
+ checkpoint_timeout = "15 min";
+ checkpoint_completion_target = 0.9;
+ max_wal_size = "1024 MB";
+ min_wal_size = "512 MB";
+
+ # WAL writing
+ wal_compression = "on";
+ wal_buffers = -1; # auto-tuned by Postgres till maximum of segment size (16MB by default).
+ wal_writer_delay = "200ms";
+ wal_writer_flush_after = "1MB";
+
+ # Background writer
+ bgwriter_delay = "200ms";
+ bgwriter_lru_maxpages = 100;
+ bgwriter_lru_multiplier = 2.0;
+ bgwriter_flush_after = 0;
+
+ # Parallel queries
+ max_worker_processes = 2;
+ max_parallel_workers_per_gather = 1;
+ max_parallel_maintenance_workers = 1;
+ max_parallel_workers = 2;
+ parallel_leader_participation = "on";
+
+ # Advanced features
+ enable_partitionwise_join = "on";
+ enable_partitionwise_aggregate = "on";
+ jit = "on";
+ max_slot_wal_keep_size = "1000 MB";
+ track_wal_io_timing = "on";
+ };
+ };
+}
diff --git a/hosts/cube/prometheus.nix b/hosts/cube/prometheus.nix
new file mode 100644
index 0000000..66c9d60
--- /dev/null
+++ b/hosts/cube/prometheus.nix
@@ -0,0 +1,42 @@
+{ self, config, lib, ... }: let
+ inherit (lib) enabled filterAttrs flatten mapAttrsToList;
+in {
+ services.grafana.provision.datasources.settings = {
+ datasources = [{
+ name = "Prometheus";
+ type = "prometheus";
+ url = "http://[::1]:${toString config.services.prometheus.port}";
+
+ orgId = 1;
+ }];
+
+ deleteDatasources = [{
+ name = "Prometheus";
+ orgId = 1;
+ }];
+ };
+
+ services.prometheus = enabled {
+ listenAddress = "[::]";
+ retentionTime = "1w";
+
+ scrapeConfigs = let
+ configToScrapeConfig = hostName: { hostConfig, ... }:
+ hostConfig.services.prometheus.exporters
+ |> filterAttrs (exporterName: exporterConfig:
+ exporterName != "minio" &&
+ exporterName != "unifi-poller" &&
+ exporterConfig.enable or false)
+ |> mapAttrsToList (exporterName: exporterConfig: {
+ job_name = "${exporterName}-${hostName}";
+
+ static_configs = [{
+ targets = [ "${hostName}:${toString exporterConfig.port}" ];
+ }];
+ });
+
+ in self.nixosConfigurations
+ |> mapAttrsToList configToScrapeConfig
+ |> flatten;
+ };
+}
diff --git a/hosts/disk/default.nix b/hosts/disk/default.nix
index abd05e9..87d6683 100644
--- a/hosts/disk/default.nix
+++ b/hosts/disk/default.nix
@@ -40,8 +40,8 @@ in {
in {
hostName = "disk";
- ipv4 = "23.164.232.40";
- ipv6 = "2602:f9f7::40";
+ ipv4.address = "23.164.232.40";
+ ipv6.address = "2602:f9f7::40";
domain = "rgbcu.be";
diff --git a/hosts/disk/id.age b/hosts/disk/id.age
index 4ff9d0a..1b3df6e 100644
Binary files a/hosts/disk/id.age and b/hosts/disk/id.age differ
diff --git a/hosts/disk/password.floppy.age b/hosts/disk/password.floppy.age
index 22d78fe..ff3b412 100644
--- a/hosts/disk/password.floppy.age
+++ b/hosts/disk/password.floppy.age
@@ -1,7 +1,7 @@
age-encryption.org/v1
--> ssh-ed25519 spFFQA pJguGLlB7R7iXrGfwKabGxmryMrfY57yvfaCytZG/Fs
-1USXbjiteoTrs7+KEFPTMVBNHpBWFXyHi/iLxFL7tls
--> ssh-ed25519 CzqbPQ IbK7nvEUn324R2zHDJzfgMV/FDqwLCU/jGZLSjrG4FY
-naDshlcyrpvgLQydqxAXg/hhfFAFov568p163F7wrZ4
---- MTj/7Zs1N348gDK+G1p01d6EZ21JzpPJnlaUc1ChcBo
-*luM=&Z0!A3e\B0VښR; \6ֹo^ZR}_%~k o$O$^A*
\ No newline at end of file
+-> ssh-ed25519 spFFQA YsTLrDcLvotgvQQJCD6DBH33gYQ9AqYaGcr190cG3TI
+3q4i1UfAG7EnjhIxZaeQWQY8vcJr6JK7/LM3yP2Gao0
+-> ssh-ed25519 CzqbPQ e8RuAwnyVxk0Yuh7xHcrGYhhBH7GOJkJMxrIzgIcny8
+RCoXTagYrg7uX/XG9UCY794a4d+ClM8vYbkZCw6Sw0Q
+--- 62b4Fu14qheY/e7ffDWERVQIrLrxl9yKdVWmuMD+ZSA
+|aלp6}[TU>{V#7" SӍMOF1)3@75>Ktu2$W"v
\ No newline at end of file
diff --git a/hosts/nine/default.nix b/hosts/nine/default.nix
index a6de34f..97f53b3 100644
--- a/hosts/nine/default.nix
+++ b/hosts/nine/default.nix
@@ -40,8 +40,8 @@ in {
in {
hostName = "nine";
- ipv4 = "152.53.2.105";
- ipv6 = "2a0a:4cc0:0:12d9::";
+ ipv4.address = "152.53.2.105";
+ ipv6.address = "2a0a:4cc0:0:12d9::";
domain = "rgbcu.be";
diff --git a/hosts/nine/github2forgejo/environment.age b/hosts/nine/github2forgejo/environment.age
index 1373ee0..8fc0e00 100644
Binary files a/hosts/nine/github2forgejo/environment.age and b/hosts/nine/github2forgejo/environment.age differ
diff --git a/hosts/nine/id.age b/hosts/nine/id.age
index 42f0b9f..acfc099 100644
Binary files a/hosts/nine/id.age and b/hosts/nine/id.age differ
diff --git a/hosts/nine/password.seven.age b/hosts/nine/password.seven.age
index 21078a4..f416141 100644
--- a/hosts/nine/password.seven.age
+++ b/hosts/nine/password.seven.age
@@ -1,7 +1,7 @@
age-encryption.org/v1
--> ssh-ed25519 dASlBQ jbiIxrysHZ21MCvz4L+lbmi3GMH32ZRy+q/pNBkSqW0
-j2j3uQhWnvrCRNg0+cSwCz3/NNhQ3845h2bzCWMv3kQ
--> ssh-ed25519 CzqbPQ u1JW2+Ti8JtHDLgvDFcKwVPPzSSQvNru4OOEMdGGhlQ
-4AWUfqUzfT35ijv7rlqdnm0CGWOC4zQIpCWI+JYVWY4
---- CtfGHevr6FqzOYK/REhFlxAy08LOgt+3+DJz9tZPNp0
-CB1D˵QC"B<*1UpE6NoGNQ> ?U#59\pH\q+DYk`kχuOM
\ No newline at end of file
+-> ssh-ed25519 dASlBQ QgmiZTOwtv6WXw/1tqHg53H7lH/ZYSYN932+desFFQo
+p/1V5QZ9vrCOSvoSBKIPoIKAUXjdYXhovZkvRam2Yb0
+-> ssh-ed25519 CzqbPQ 7AN7/Dm9Iv4hQEELZyxKk74kJuDzv/veAHcPj3P3a0g
+miUBnlLKmwsbY/OirayxJO3VQrdn/6HDGwONlMoKWlQ
+--- trEYZUoukCFgpo/LwUW+0/ggQ0X0Chyyx/0TXRgsF58
+0zUTWҪ*Lt0S֚X,1>5esdKEU'|A"Q{?ժj}}4^&(9}
\ No newline at end of file
diff --git a/lib/system.nix b/lib/system.nix
index e0feaa5..0aed4cd 100644
--- a/lib/system.nix
+++ b/lib/system.nix
@@ -1,9 +1,9 @@
inputs: self: super: let
inherit (self) attrValues filter getAttrFromPath hasAttrByPath collectNix;
- commonModules = collectNix ../modules/common;
- nixosModules = collectNix ../modules/linux;
- darwinModules = collectNix ../modules/darwin;
+ modulesCommon = collectNix ../modules/common;
+ modulesLinux = collectNix ../modules/linux;
+ modulesDarwin = collectNix ../modules/darwin;
collectInputs = let
inputs' = attrValues inputs;
@@ -11,8 +11,8 @@ inputs: self: super: let
|> filter (hasAttrByPath path)
|> map (getAttrFromPath path);
- inputNixosModules = collectInputs [ "nixosModules" "default" ];
- inputDarwinModules = collectInputs [ "darwinModules" "default" ];
+ inputModulesLinux = collectInputs [ "nixosModules" "default" ];
+ inputModulesDarwin = collectInputs [ "darwinModules" "default" ];
inputOverlays = collectInputs [ "overlays" "default" ];
overlayModule = { nixpkgs.overlays = inputOverlays; };
@@ -30,9 +30,9 @@ in {
modules = [
module
overlayModule
- ] ++ commonModules
- ++ nixosModules
- ++ inputNixosModules;
+ ] ++ modulesCommon
+ ++ modulesLinux
+ ++ inputModulesLinux;
};
darwinSystem = module: super.darwinSystem {
@@ -41,8 +41,8 @@ in {
modules = [
module
overlayModule
- ] ++ commonModules
- ++ darwinModules
- ++ inputDarwinModules;
+ ] ++ modulesCommon
+ ++ modulesDarwin
+ ++ inputModulesDarwin;
};
}
diff --git a/modules/acme/default.nix b/modules/acme/default.nix
index a802747..a1cc3ca 100644
--- a/modules/acme/default.nix
+++ b/modules/acme/default.nix
@@ -2,11 +2,11 @@
inherit (config.networking) domain;
inherit (lib) mkValue;
in {
- options.acmeUsers = mkValue [];
+ options.security.acme.users = mkValue [];
config.secrets.acmeEnvironment.file = ./environment.age;
- config.users.groups.acme.members = config.acmeUsers;
+ config.users.groups.acme.members = config.security.acme.users;
config.security.acme = {
acceptTerms = true;
diff --git a/modules/acme/environment.age b/modules/acme/environment.age
index e894173..75501e3 100644
--- a/modules/acme/environment.age
+++ b/modules/acme/environment.age
@@ -1,11 +1,12 @@
age-encryption.org/v1
--> ssh-ed25519 +rZ0Tw DMMzxXSIPSsRLkIvKJAiE6OzV1z3EZ0T+od2iIxMiA0
-OHVLHmVzeiWlsVI+DQ5M+iNik+nsdiQBz4zcquygC0A
--> ssh-ed25519 spFFQA TVqArtAoudQlrgAqshCP8ZU0YlVZoKwkvUVh968NqC8
-Cy7+Y1rTFiAoWp6Gw8a1cljCjWPHtNwXjlXWQyu8A8U
--> ssh-ed25519 dASlBQ ui5a61Tg1JoJvR8okc8qKkDhrSE9dH84XZQWhLn7cCo
-5ehK2bvVgLZSYr5AstV1dwW7/qaVGRxs8PdzAg7sk4w
--> ssh-ed25519 CzqbPQ wgktFhPRIAwX8BNJu8svEHDrpz0ZCOw94nR+M3FJCTY
-RAErTHg/g/voC7yPf2lB+ELmysNwQXre9jucw2y+ZVc
---- AB7oiyhts6riNlp5xuWsFTzIx2y7Axn0CU4uCXHfVLo
-`8eߧJST'BězgK
zꚉWcFݸ3ᇴGR}Rיq6]n0b<+dԴ\ECMUͱ3 X{qjʁE0&M8xtʈF }/Oq_:ҟ0(I/hKHK\X\'(gbAܐ
\ No newline at end of file
+-> ssh-ed25519 +rZ0Tw 9CETPqa+HdfpR1kRho1QnotNGFsLCVh64oRzP6DoF3Q
+nZ6qcscZQ3Auct11BaM0jsYLyGnseDQ7OwQgSvLqGDw
+-> ssh-ed25519 spFFQA 3oJSVeOECqU6ZkxLWErgrfn/3pLEEaJGy64OiGLvsXM
+dt7obdmMHz4rGJxqQuZm9ptbCbJmxk80s3ME0FNQWuI
+-> ssh-ed25519 dASlBQ A0OQkTL89cmKOhFlHerq98XxdEqn/EaXB+DlTbaGG2c
+X8sG3M7BEPrey204Bs2kLuiPI+r4LKvIVD+Xdz/Vfxk
+-> ssh-ed25519 CzqbPQ ZU/Fb5/XYBD9RQjMC4IQwQPSouotxFNWVpKdCsetNQk
+o97rTb0aofBUmjPyrY11NwE33az7+HxbYUlw6cjE9GU
+--- 8wtobvBFTd1V1idugrE6xnI1/QW/StCrcO6IjrRl/cQ
+}KzLD(џ_̲tV~N֥^'5\H.7Թh map (splitString "#")
|> map head;
diff --git a/modules/linux/endlessh-go.nix b/modules/linux/endlessh-go.nix
index 3698c86..8aefb0c 100644
--- a/modules/linux/endlessh-go.nix
+++ b/modules/linux/endlessh-go.nix
@@ -1,7 +1,7 @@
{ config, lib, pkgs, ... }: let
inherit (lib) enabled mkEnableOption mkIf mkOption types;
- fakeSSHPort = 22;
+ portFakeSSH = 22;
in {
config.services.prometheus.exporters.endlessh-go = mkIf config.isServer <| enabled {
listenAddress = "[::]";
@@ -10,11 +10,11 @@ in {
# `services.endlessh-go.openFirewall` exposes both the Prometheus
# exporters port and the SSH port, and we don't want the metrics
# to leak, so we manually expose this like so.
- config.networking.firewall.allowedTCPPorts = mkIf config.isServer <| [ fakeSSHPort ];
+ config.networking.firewall.allowedTCPPorts = mkIf config.isServer <| [ portFakeSSH ];
config.services.endlessh-go = mkIf config.isServer <| enabled {
listenAddress = "[::]";
- port = fakeSSHPort;
+ port = portFakeSSH;
extraOptions = [
"-alsologtostderr"
diff --git a/modules/linux/hyprland/hyprland.nix b/modules/linux/hyprland/hyprland.nix
index cfe6132..4a70e0c 100644
--- a/modules/linux/hyprland/hyprland.nix
+++ b/modules/linux/hyprland/hyprland.nix
@@ -8,12 +8,12 @@ in merge <| mkIf config.isDesktop {
xdg.portal = enabled {
config.common.default = "*";
- extraPortals = with pkgs; [
- xdg-desktop-portal-hyprland
+ extraPortals = [
+ pkgs.xdg-desktop-portal-hyprland
];
- configPackages = with pkgs; [
- hyprland
+ configPackages = [
+ pkgs.hyprland
];
};
@@ -50,7 +50,7 @@ in merge <| mkIf config.isDesktop {
enableXdgAutostart = true;
};
- # plugins = with pkgs; [ hyprcursors ];
+ # plugins = [ pkgs.hyprcursors ];
# settings.plugin.dynamic-cursors = {
# mode = "rotate";
diff --git a/modules/linux/ip.nix b/modules/linux/ip.nix
index 15dac4a..bd39671 100644
--- a/modules/linux/ip.nix
+++ b/modules/linux/ip.nix
@@ -3,14 +3,12 @@
inherit (lib) optionals;
in {
networking.interfaces.${interface} = {
- ipv4.addresses = optionals (config.networking.ipv4 != null) [{
- address = config.networking.ipv4;
- prefixLength = 22;
+ ipv4.addresses = optionals (config.networking.ipv4.address != null) [{
+ inherit (config.networking.ipv4) address prefixLength;
}];
- ipv6.addresses = optionals (config.networking.ipv4 != null) [{
- address = config.networking.ipv6;
- prefixLength = 64;
+ ipv6.addresses = optionals (config.networking.ipv4.address != null) [{
+ inherit (config.networking.ipv6) address prefixLength;
}];
};
}
diff --git a/modules/linux/resolved.nix b/modules/linux/resolved.nix
index 85f8c61..c736bee 100644
--- a/modules/linux/resolved.nix
+++ b/modules/linux/resolved.nix
@@ -1,14 +1,14 @@
{ config, lib, ... }: let
- inherit (lib) enabled concatStringsSep map;
+ inherit (lib) enabled concatStringsSep;
in {
services.resolved = enabled {
dnssec = "true";
dnsovertls = "true";
- extraConfig = config.dnsServers
+ extraConfig = config.networking.dns.servers
|> map (server: "DNS=${server}")
|> concatStringsSep "\n";
- fallbackDns = config.fallbackDnsServers;
+ fallbackDns = config.networking.dns.serversFallback;
};
}
diff --git a/modules/linux/restic/default.nix b/modules/linux/restic/default.nix
index c2801a7..4c9fd4a 100644
--- a/modules/linux/restic/default.nix
+++ b/modules/linux/restic/default.nix
@@ -1,11 +1,11 @@
{ config, lib, ... }: let
inherit (lib) genAttrs mkConst mkIf remove;
in{
- options.resticHosts = mkConst <| remove config.networking.hostName [ "cube" "disk" "nine" ];
+ options.services.restic.hosts = mkConst <| remove config.networking.hostName [ "cube" "disk" "nine" ];
config.secrets.resticPassword.file = mkIf config.isServer ./password.age;
- config.services.restic.backups = mkIf config.isServer <| genAttrs config.resticHosts (host: {
+ config.services.restic.backups = mkIf config.isServer <| genAttrs config.services.restic.hosts (host: {
repository = "sftp:backup@${host}:${config.networking.hostName}-backup";
passwordFile = config.secrets.resticPassword.path;
initialize = true;
diff --git a/modules/linux/restic/password.age b/modules/linux/restic/password.age
index dfe39fc..cc78dce 100644
Binary files a/modules/linux/restic/password.age and b/modules/linux/restic/password.age differ
diff --git a/modules/mail/default.nix b/modules/mail/default.nix
index 2d68cdc..d9538f8 100644
--- a/modules/mail/default.nix
+++ b/modules/mail/default.nix
@@ -10,11 +10,11 @@ in {
listenAddress = "[::]";
};
- services.restic.backups = genAttrs config.resticHosts <| const {
+ services.restic.backups = genAttrs config.services.restic.hosts <| const {
paths = [ config.mailserver.dkimKeyDirectory config.mailserver.mailDirectory ];
};
- acmeUsers = [ "mail" ];
+ security.acme.users = [ "mail" ];
mailserver = enabled {
domains = mkDefault [ domain ];
diff --git a/modules/mail/password.hash.age b/modules/mail/password.hash.age
index 8347272..6a1d85e 100644
Binary files a/modules/mail/password.hash.age and b/modules/mail/password.hash.age differ
diff --git a/modules/mail/password.plain.age b/modules/mail/password.plain.age
index 917472f..39151da 100644
Binary files a/modules/mail/password.plain.age and b/modules/mail/password.plain.age differ
diff --git a/modules/nginx.nix b/modules/nginx.nix
index 09e4487..f5aa742 100644
--- a/modules/nginx.nix
+++ b/modules/nginx.nix
@@ -2,13 +2,13 @@
inherit (config.networking) domain;
inherit (lib) enabled mkConst;
in {
- options.nginxSslTemplate = mkConst {
+ options.nginx.sslTemplate = mkConst {
forceSSL = true;
quic = true;
useACMEHost = config.networking.domain;
};
- options.nginxHeaders = mkConst ''
+ options.nginx.headers = mkConst ''
# TODO: Not working for some reason.
add_header Access-Control-Allow-Origin $allow_origin;
add_header Access-Control-Allow-Methods $allow_methods;
@@ -33,7 +33,7 @@ in {
listenAddress = "[::]";
};
- config.acmeUsers = [ "nginx" ];
+ config.security.acme.users = [ "nginx" ];
config.services.nginx = enabled {
package = pkgs.nginxQuic;
@@ -61,7 +61,7 @@ in {
~^https://.+\.${domain}$ "GET, HEAD, OPTIONS";
}
- ${config.nginxHeaders}
+ ${config.nginx.headers}
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
'';
diff --git a/modules/site.nix b/modules/site.nix
index 6705a04..55c2d9e 100644
--- a/modules/site.nix
+++ b/modules/site.nix
@@ -2,22 +2,22 @@
inherit (config.networking) domain;
inherit (lib) enabled merge;
- sitePath = "/var/www/site";
+ pathSite = "/var/www/site";
- notFoundLocationConfig = {
+ configNotFoundLocation = {
extraConfig = "error_page 404 /404.html;";
locations."/404".extraConfig = "internal;";
};
in {
services.nginx = enabled {
- virtualHosts.${domain} = merge config.nginxSslTemplate notFoundLocationConfig {
- root = sitePath;
+ virtualHosts.${domain} = merge config.nginx.sslTemplate configNotFoundLocation {
+ root = pathSite;
locations."/".tryFiles = "$uri $uri.html $uri/index.html =404";
locations."/assets/".extraConfig = ''
if ($request_method = OPTIONS) {
- ${config.nginxHeaders}
+ ${config.nginx.headers}
add_header Content-Type text/plain;
add_header Content-Length 0;
return 204;
@@ -27,12 +27,12 @@ in {
'';
};
- virtualHosts."www.${domain}" = merge config.nginxSslTemplate {
+ virtualHosts."www.${domain}" = merge config.nginx.sslTemplate {
locations."/".extraConfig = "return 301 https://${domain}$request_uri;";
};
- virtualHosts._ = merge config.nginxSslTemplate notFoundLocationConfig {
- root = sitePath;
+ virtualHosts._ = merge config.nginx.sslTemplate configNotFoundLocation {
+ root = pathSite;
locations."/".extraConfig = "return 404;";
locations."/assets/".extraConfig = "return 301 https://${domain}$request_uri;";
diff --git a/secrets.nix b/secrets.nix
index 1476caa..53ac6cf 100644
--- a/secrets.nix
+++ b/secrets.nix
@@ -1,14 +1,23 @@
let
- inherit (import ./keys.nix) disk nine admins all;
+ inherit (import ./keys.nix) cube disk nine admins all;
in {
+ # cube
+ "hosts/cube/forgejo/password.runner.age".publicKeys = [ cube ] ++ admins;
+ "hosts/cube/grafana/password.age".publicKeys = [ cube ] ++ admins;
+ "hosts/cube/id.age".publicKeys = [ cube ] ++ admins;
+ "hosts/cube/matrix/password.secret.age".publicKeys = [ cube ] ++ admins;
+ "hosts/cube/matrix/password.sync.age".publicKeys = [ cube ] ++ admins;
+ "hosts/cube/nextcloud/password.age".publicKeys = [ cube ] ++ admins;
+ "hosts/cube/password.rgb.age".publicKeys = [ cube ] ++ admins;
+
# disk
- "hosts/disk/password.floppy.age".publicKeys = [ disk ] ++ admins;
"hosts/disk/id.age".publicKeys = [ disk ] ++ admins;
+ "hosts/disk/password.floppy.age".publicKeys = [ disk ] ++ admins;
# nine
+ "hosts/nine/github2forgejo/environment.age".publicKeys = [ nine ] ++ admins;
"hosts/nine/id.age".publicKeys = [ nine ] ++ admins;
"hosts/nine/password.seven.age".publicKeys = [ nine ] ++ admins;
- "hosts/nine/github2forgejo/environment.age".publicKeys = [ nine ] ++ admins;
# shared
"modules/common/ssh/config.age".publicKeys = all;