DEVELOPMENT ENVIRONMENT

~liljamo/nix-arta

ba8b726b9073444ad8c86d2e87e4ac28e91fff7b — Jonni Liljamo 2 months ago 4547209
feat: add cloud
M .sops.yaml => .sops.yaml +7 -0
@@ 6,6 6,7 @@ keys:
    # LXCs
  - &alderaan age1h57c3pw5y450yeex3yhlarkaeur5n3le09lm4frf8d3q3qpagfzqdqxm83
  - &auth age1wu70y79zuqtk2z5q3t4vvwns2qmerwsy4gn4czf5f4xhch3yquksfwq0q4
  - &cloud age17cw2ynlaw0ruga0u5678vas50k7neevuufk7gsqn8y8673g0mu8szhx4lr
  - &dns age1m5ktjargxxu04dn9c2uhvaw79z74mxsc4vdrkalxjn4aa8c86plqg0hyyw
  - &metrics age1m8u3a7rzyx2n6zjxjnfkla34yk3v77egxzd3lv9umt69lsynlaqqqfpt05
  - &social age173lqcfnq2a3xwdjkdua6uqyskfhpdqp2lt4jskdkg3rfqv23vu2sgplq98


@@ 37,6 38,12 @@ creation_rules:
      - *liljamo_gpg
      age:
      - *auth
  - path_regex: secrets/cloud/[^/]+\.yaml$
    key_groups:
    - pgp:
      - *liljamo_gpg
      age:
      - *cloud
  - path_regex: secrets/dns/[^/]+\.yaml$
    key_groups:
    - pgp:

A hosts/cloud/default.nix => hosts/cloud/default.nix +20 -0
@@ 0,0 1,20 @@
{config, ...}: {
  sops.secrets.rootPwd.neededForUsers = true;
  sops.secrets.liljamoPwd.neededForUsers = true;

  # Outline is under BSL1.1
  arta.unfree.allow = ["outline"];

  roles.base = {
    root.hashedPasswordFile = config.sops.secrets.rootPwd.path;
    primaryUser = {
      username = "liljamo";
      hashedPasswordFile = config.sops.secrets.liljamoPwd.path;
    };
  };

  roles.tailscale = {
    enable = true;
    enableSSH = true;
  };
}

A secrets/cloud/secrets.yaml => secrets/cloud/secrets.yaml +42 -0
@@ 0,0 1,42 @@
rootPwd: ENC[AES256_GCM,data:XwfHY6qCxwYOtoKxYp+3gbx2JQpVDrq/KpFdLuSy0Mb026+ixrncicEw4E3R9iq9MnRZJpoauGxw1XQlBcvF2kx2sXZAnQxpHWGPZTunntTiDij/n6ahKbIuGqQHDAzc8KKlnRdCIebgEw==,iv:oAicqT0VJqjWI/Al/aLRDF0rEqCANmUuaml9aR1vKko=,tag:DDzOKvnsKSxZqosJM/gYnw==,type:str]
liljamoPwd: ENC[AES256_GCM,data:kp7QlA523jH3b5QyDqYAehd4vc01HqIqbbZwdVKY0mA6uiqFeUk7PMDwuH7NRnCGD8msaC3gyUUglBtWs3XGWukDA8H+lw5ZqCDaRD+KESURc3/s+LABiUf8Zwm6Dj5zWRmLctot85BWsA==,iv:VevfwnY1YpIRsSFd39cfuioPkGC3PSLlDbCXNmOuwXI=,tag:/e5L2CRWRHeppbyjAmf6gw==,type:str]
outline:
    secretKey: ENC[AES256_GCM,data:POFzIrLEWmOAu2+53nD8KIJQ0q6oeDKdzpikfuNwxvjXfORwcG7QXjSU8wWfCXORbrT5knh7rcU9yvvBZXVObQ==,iv:f8dULXac9C6vnXZRvKhIc6WyVYl5eF/nrUs7ZCNdPYQ=,tag:boO+R3ny01WZfHT4WyEJ6A==,type:str]
    utilsSecret: ENC[AES256_GCM,data:MUluti1wd8x0z5eIVcPi4n5cmOLBBanM9pRQYPonxbJVAGuPrrfDLGJ8OrqNJGzrN4LmdW57Mhn0kAYf6Jl4Gw==,iv:pM6QdHK1xnYdu+zIoYlBirdhWaZbgud/2IqRO22jHbM=,tag:XOfeAO8DS60Ei8Rq2VofaA==,type:str]
    oidcSecret: ENC[AES256_GCM,data:Cf5yh1nXCtKhJVmXqzGvLlZ4gL41XBg4ZuvFEFtu9NcO5kfpV+T22Ntg9nbQ6WK8nThNV4wplrGAbSlOE8n1fQ==,iv:Tp+VgLdB9HxN5gi8nJLuoqrwXBAfb+njcFdGPXiUhAk=,tag:sFUlCxHnIpAhjmqg2aVbCg==,type:str]
    smtpPwd: ENC[AES256_GCM,data:z+Uh6h2shWBj/iQ7Xrrh5jyH2py0hTaWxXvwMTCMXR4keoLFXEA9T039nZEkA88+26IkXMPH2Sv01ijaMVJMaaE8M0bwBqf399l03jYhpkIaJ9q6dno0bwHgg2QhF9fk/kPxne5ScazOZtSBuYun85zev82YjYGlb+5jbrpYU+M=,iv:oWYM48IY1QIiS7RSaTjfuSIIAGQrWGtDQJyA6vu3OwQ=,tag:as9Y+i9LTqtvQIhuF9bITw==,type:str]
nextcloud:
    adminpass: ENC[AES256_GCM,data:DrjQXb0ua9dfemyRaoRhZ+jgiZRvH8xa7sIcj9O22O8Nmz0DvYe6sHaaIbnJKNr4vttAZSIXIZ8Z2EopxPlwlaTjsyI2/CQmW4VJq5R5GqyQdfdcLFsO/Yjc9LLGaaMqM2LEgtBPZ8MsCzIrAxOuSRPl6EGL+CUfMfsxdl4Iv8E=,iv:lEvKJ8HxcTUs1mylhqOMHs9V/KGkv5YOdHyZMnIyc78=,tag:DqK101a3idk40+MmjKOrnA==,type:str]
    dbpass: ENC[AES256_GCM,data:JFjdXW1K8HwW,iv:TJQuf1uftrNs6oXi6zxquu7w7iwwKrL7ljCjVLwbVUo=,tag:7kgtyJilrO0pG1avxielKQ==,type:str]
sops:
    kms: []
    gcp_kms: []
    azure_kv: []
    hc_vault: []
    age:
        - recipient: age17cw2ynlaw0ruga0u5678vas50k7neevuufk7gsqn8y8673g0mu8szhx4lr
          enc: |
            -----BEGIN AGE ENCRYPTED FILE-----
            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMaDBZcStOMzRpVzNBNUIx
            ZmpDdkt4ZW1KUmRDUnhaN3dmK1ZseFVJMlRjCjhaTGcvR3FpMGdNcmpNeVQ1Q3lk
            cUUxaTJaMG1vOVpFbGtRQkVlQkIyUVkKLS0tIHIrZk9HUkVsNjUvOFVwTmwzaFZu
            TjduMkxMazUveTlUdStwRGJaRDlpaTAKW7P6B3W1tih2S81TRY7m/Me9Gr6CwZLi
            Wymq21dT+Or2FR8F2LZDHG8WiUOu/8bvSZ0ZYZpfs5mCvufdRhPFaA==
            -----END AGE ENCRYPTED FILE-----
    lastmodified: "2024-09-09T17:30:36Z"
    mac: ENC[AES256_GCM,data:Vhz/eGr3oC9eIil13kDrct3o1SyUB85ZQ+Ho8HSLeDyj6cgqPLqM5GoZlzE/ttR9VZN0FXJpULWMq/0jyiJbpTMh24jj0+iPTBHzagAyjeXSboOh3FQ04FIoDB20+o4gmmHhPjk1F9HuWwzc0dcO4WgHCC7QWPBL0I0uX3Vmpuw=,iv:bbohTgOSzgo4M6eeG17VSy0Tf84vI9svFnrsvKALdok=,tag:mo9MQuVgtuaDfyw7vfKz7Q==,type:str]
    pgp:
        - created_at: "2024-09-09T17:25:01Z"
          enc: |-
            -----BEGIN PGP MESSAGE-----

            hF4D8ab0ENzkR4wSAQdATt7SdwiDH6aKlpyPYFBTBv81i3jqM2mu8w0HuqH+TUYw
            dkPasoA93vwwYBekgO1WwcLa31kY57G0DoUHx5YngKEmumFC5TGajeUioCCLGVQM
            1GYBCQIQAtIQhO5N2qT5sSPnik2uDttAma9Y0iigY9ZJ0C3AH0O5J53TZOIBVqw5
            aWHgwFoDkNULMBaM9iUjcICuXdoVXD6ILGPgXE2uhar/FCqHlv8MFQOSW/luIsGg
            uYnNZ/yu4Ts=
            =0s/b
            -----END PGP MESSAGE-----
          fp: 848EEBCEE9F0D29D25C321A658577946A65EB712
    unencrypted_suffix: _unencrypted
    version: 3.8.1

A systems/hosts/cloud/default.nix => systems/hosts/cloud/default.nix +191 -0
@@ 0,0 1,191 @@
{
  config,
  lib,
  pkgs,
  ...
}: let
  outlinePort = 3000;
in {
  networking.firewall.allowedTCPPorts = [80 config.services.outline.port];

  sops.secrets."outline/secretKey" = {
    owner = "outline";
    group = "outline";
  };
  sops.secrets."outline/utilsSecret" = {
    owner = "outline";
    group = "outline";
  };
  sops.secrets."outline/oidcSecret" = {
    owner = "outline";
    group = "outline";
  };
  sops.secrets."outline/smtpPwd" = {
    owner = "outline";
    group = "outline";
  };
  sops.secrets."nextcloud/adminpass" = {
    owner = "nextcloud";
    group = "nextcloud";
  };
  sops.secrets."nextcloud/dbpass" = {
    owner = "nextcloud";
    group = "nextcloud";
  };

  environment.systemPackages = with pkgs; [
    ffmpeg-headless
    gnumake
    nodePackages_latest.nodejs
    nodePackages_latest.node-pre-gyp
    python3
  ];
  users.users.nextcloud.extraGroups = ["render" "users"];

  services = {
    nextcloud = {
      enable = true;
      package = pkgs.nextcloud29;
      caching = {
        redis = true;
      };
      config = {
        adminpassFile = config.sops.secrets."nextcloud/adminpass".path;
        adminuser = "admin";
        dbhost = "127.0.0.1:5432";
        dbname = "nextcloud";
        dbtype = "pgsql";
        dbuser = "nextcloud";
        dbpassFile = config.sops.secrets."nextcloud/dbpass".path;
      };
      configureRedis = true;
      settings = {
        default_phone_region = "FI";
        loglevel = 2;
        log_type = "file";
        maintenance_window_start = 0; # Maintenance window from UTC 0000 to 0400
        redis = {
          host = "/run/redis-nextcloud/redis.sock";
        };
        trusted_domains = ["nextcloud.rustylily.home.arpa"];
        trusted_proxies = ["10.1.2.10"];
        opcache.interned_strings_buffer = 64; # Megabytes of memory to use
        overwriteprotocol = "https";

        # Programs needed for... stuff.
        preview_ffmpeg_path = "${lib.getExe pkgs.ffmpeg}";
        memories.exiftool = "${lib.getExe pkgs.exiftool}";
        memories.exiftool_no_local = true;
        memories.ffmpeg_path = "${pkgs.ffmpeg-headless}/bin/ffmpeg";
        memories.ffprobe_path = "${pkgs.ffmpeg-headless}/bin/ffprobe";
        memories.vod.ffmpeg = "${pkgs.ffmpeg-headless}/bin/ffmpeg";
        memories.vod.ffprobe = "${pkgs.ffmpeg-headless}/bin/ffprobe";
      };
      hostName = "cloud.liljamo.com";
      https = true;
      maxUploadSize = "2048M";
      phpOptions."output_buffering" = "0";
      phpExtraExtensions = all: [all.pdlib all.bz2];
    };
    outline = {
      enable = true;
      port = outlinePort;
      user = "outline";
      group = "outline";
      databaseUrl = "postgres://outline:outline@127.0.0.1/outline?sslmode=disable";
      redisUrl = "redis://127.0.0.1:3079";
      enableUpdateCheck = false;
      maximumImportSize = 5120000;
      publicUrl = "https://docs.liljamo.com";
      secretKeyFile = config.sops.secrets."outline/secretKey".path;
      utilsSecretFile = config.sops.secrets."outline/utilsSecret".path;
      storage = {
        storageType = "local";
      };
      oidcAuthentication = {
        authUrl = "https://auth.liljamo.com/api/oidc/authorization";
        clientId = "outline";
        clientSecretFile = config.sops.secrets."outline/oidcSecret".path;
        displayName = "Liljamo Auth";
        scopes = ["openid" "offline_access" "profile" "email"];
        tokenUrl = "https://auth.liljamo.com/api/oidc/token";
        userinfoUrl = "https://auth.liljamo.com/api/oidc/userinfo";
        usernameClaim = "preferred_username";
      };
      smtp = {
        host = "smtp.migadu.com";
        port = 465;
        fromEmail = "outline@liljamo.com";
        replyEmail = "outline@liljamo.com";
        username = "outline@liljamo.com";
        passwordFile = config.sops.secrets."outline/smtpPwd".path;
      };
    };
    postgresql = {
      package = pkgs.postgresql_15;
      enable = true;
      settings.port = 5432;
      ensureDatabases = ["outline" "nextcloud"];
      ensureUsers = [
        {
          name = "outline"; # needs to match the user that's running outline
          ensureDBOwnership = true;
        }
        {
          name = "nextcloud";
          ensureDBOwnership = true;
        }
      ];
    };
    redis.servers = {
      outline = {
        enable = true;
        bind = "127.0.0.1";
        port = 3079;
      };
      nextcloud = {
        enable = true;
        bind = "127.0.0.1";
        port = 3179;
      };
    };
  };

  systemd = {
    timers = {
      nextcloud-update-files = {
        wantedBy = ["timers.target"];
        timerConfig = {
          OnBootSec = "2m";
          OnUnitActiveSec = "15m";
          Unit = "nextcloud-update-files.service";
        };
      };
    };
    services = {
      nextcloud-cron.path = [pkgs.perl];
      nextcloud-update-files = {
        bindsTo = ["postgresql.service" "phpfpm-nextcloud.service"];
        after = ["postgresql.service" "phpfpm-nextcloud.service"];
        script = ''
          ${config.services.nextcloud.occ}/bin/nextcloud-occ files:scan -q --all
          ${config.services.nextcloud.occ}/bin/nextcloud-occ preview:pre-generate
        '';
        serviceConfig.User = "nextcloud";
        path = ["config.services.nextcloud" pkgs.perl];
      };
      nextcloud-occ-settings = {
        after = ["nextcloud-setup.service"];
        serviceConfig = {
          Type = "oneshot";
          User = "nextcloud";
        };
        script = ''
          ${config.services.nextcloud.occ}/bin/nextcloud-occ config:app:set dav system_addressbook_exposed --value="no"
        '';
      };
    };
  };

  system.stateVersion = "24.05";
}

M systems/hosts/default.nix => systems/hosts/default.nix +5 -0
@@ 27,6 27,11 @@
    profile = lxc;
    modules = [];
  };
  cloud = {
    system = "x86_64-linux";
    profile = lxc;
    modules = [];
  };
  dns = {
    system = "x86_64-linux";
    profile = lxc;