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;