❄️ Dotfiles for our NixOS system configuration.

feat(services): outline (test)

Chloe 2b25acaa 624b9a14

+16
secrets/minio.age
···
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGN2U2dKQSBDOTFh
+
RVVjOEI4bGF5bzgyZDVZQlEyUXlkUDRldlF2aFZ5OS8xWWlpLzI0CktPS05wd0tJ
+
aWc1bGUvMW4wdlRmdkxZaGRPZjZqU3F2bHhKdFkvencwdTgKLT4gc3NoLWVkMjU1
+
MTkgMUNUOTd3IEh1eTJhRXp4NWd6Mkl1SDU3ZTZnbW1vUkFQVWI4V2xuVGRVL2Nm
+
eE1HSGsKTDlqRjJGYUkxQW0waFV0Z2hzOFRNNTIrc1FiaVlQLzJ2YkRnajd0cDNH
+
YwotPiBzc2gtZWQyNTUxOSBlUDNUdFEgSHZQOGVyZjNPVXRjb0JKcTZJZHZiNy9z
+
NSsxZU9BZ0diTzl5ZklDNE1URQpQWFE5VjlYTjF6ZHJIUmxWYXpScGorZzZxam5Q
+
SElSVExBL1Q3bnh2NGg0Ci0+IDY6Jy9MXnQiLWdyZWFzZSBaanRiIFlnPThSCng2
+
MFo3Y3JnYnBJbzlVNFZYejJoT0U2MklZV0liUm9iSE9XcnVmRW5LdEtxVGgvLzdM
+
MjB4aisyVWhvTDFUSnkKaDNIZDdCZkZXTE5KblFFM04zdGxwK3ZPYnBPVGVkanlZ
+
TU1DejB5U3dGQUlMQQotLS0gWENCd1R5RUZKWURiaGxPQzZkL3FsQnh5ZE1lM3Nq
+
QVFoNVlFUGhiTGNOVQqSuU8Z0Wuo8GeJUsd/Zg+ngX/w4g/9o9d3itW9LEr+l5oe
+
M+/cBeFH3QZcaHN+UPKvRJbNjM9WHyL4rXKaJrDV9j6oS5v++8DLsIaHpYIVfbA3
+
DelpN2dpynRpm1rp2Q==
+
-----END AGE ENCRYPTED FILE-----
+14
secrets/outline/client-secret.age
···
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGN2U2dKQSBGNVZv
+
djhvOVJyWVpHSjJudEJSRU5SRFpMOVliVFNxVVdtQnpubkhXamxNCjdNMUhJZFNu
+
NDI2K21XTmIyL3oxZTlGN2dVV2FESzV6VDlTQmhHSGFsOTQKLT4gc3NoLWVkMjU1
+
MTkgMUNUOTd3IGVQRVlucDlESUZ6T09DcEtpU1Q1WWxEUE9KcktpUm83cmNZZDlS
+
SytpaHcKQmVLaHBqa0YzaWNoc1U5bGdmUlpHMGVpdDEzenBLbGJEaFV5RXZEeExn
+
TQotPiBzc2gtZWQyNTUxOSBlUDNUdFEgTUkvOUs1SStNL1NJSEN2WGlmN1g1cG41
+
RWR3YlRhYkJtaDl0dkJwVlVnZwpuc1lDWFpEUDIrOForV2k1VG05OHNNLzNxMlJ3
+
RUdOc1g4Y05vUDVuUExJCi0+IGU6TS1ncmVhc2UgRm4gaHAmdS9wcwpJN0FBWkRO
+
Qk50OW9FdGZMVlgvVDEzTG5CTGVFM2J5amN6a2RNR08zeGR0eGJucVkxN2QramY3
+
SlZzc3BSNHNyClhnYUFwZwotLS0gYjlkTjAyamNGa2pnSG5OV1ZZcG9LNGlacGp5
+
MDhPTnMwQUxZYjRmanRjOAr+bpss2iZCZyJskjMUJNqg8MMrUGqSTIr4Iamclg6G
+
sTC5ncGM5UJs2QIZFxD8Y03VmrA243hkPbgWYo07qOGDsg==
+
-----END AGE ENCRYPTED FILE-----
+13
secrets/outline/minio-password.age
···
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGN2U2dKQSBmMmVX
+
ZVZoRnhsUjVveDJxaVVlZHBIY0I0cERSY0VPbWdJQ0MrRjB6MFhFCkp4SkNSSXNw
+
WmRlbFV1SGRqNjR2NmFsWjQzUzhBQTJCUnNkOVRDb0FzWTAKLT4gc3NoLWVkMjU1
+
MTkgMUNUOTd3IG9BMDA0c09Rb2g3eWdkQTdnZGM5K2tabEVXRHlyWlN4dzBscU1w
+
L2xPV1kKa0tpNU5IUVlEYW9ZU3FYN2hSZWZudUFFY3JLdGk4YjRqalJjRG1LT3Nv
+
WQotPiBzc2gtZWQyNTUxOSBlUDNUdFEgTDBuRTZ6Q2dIQ0Rrc080RS81THlxcXV3
+
MzBJaVFIUGEwUGlsV1hrZDAxdwpFa3VSTC9BNG1IODhPWXU5WG01THdKYjhQRzkw
+
UXIvMnBNTllncDBxSHhVCi0+IG81TV5fKi1ncmVhc2UgTCVZZFVcCjFFTG5yTi9j
+
Wk9OdktxakVSenRaOEEKLS0tIGFUNGdQZzVzNERrR09rekZ5OERRQUVIbmI2NGVj
+
TlQ2aC9lbmdCK2pMRFEKPcBHsjWuXoUnZRv7RLiL4hf6CR32WOKqC7V8mTSAoHw1
+
LO4MEs70xBttSpwpVGdSTw==
+
-----END AGE ENCRYPTED FILE-----
+15
secrets/outline/secret-key.age
···
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGN2U2dKQSBsVlpT
+
bUJIdjZPVGRRRy8vRzhOeGEyZkdBTDI5Q2wvT25BMWtJZ1dxVVRzCngvRTV6Sy9k
+
TFZmZUl1KzlwcUNTclh3NkJsZjA0d2NxeDRodElSL3hQazgKLT4gc3NoLWVkMjU1
+
MTkgMUNUOTd3IG5PeVcwYWQ0S1VQTWwxSVcxemJQYnVKdGFMMDdDeSt4YmVjTzdv
+
VFp0QlkKZ1owb1BNczRBay9aZHNjaGV3OGlmRU8xKzB5Y1FlRjNzNmlQMlF0b2VZ
+
UQotPiBzc2gtZWQyNTUxOSBlUDNUdFEgK1M1c2xoK0swV3d3TDM5dC94WjlxWHYy
+
WEkyUkpzREdZRlpxMTJ5RGZ5RQpFdENmdlFNSnVHYVh6OWNrK1IvM1hFR0Q2TTVq
+
dEYyYUswWUpwVUpOU2lnCi0+ID4zOm9PZSktZ3JlYXNlCkt5MUNqNTRsb2NKTEJY
+
dlNFTm5JRDlsT2p2UTdXNUFCb3dhZTB5THMyc3Z5K2lrUGtmQk5GSU9UTUR1T0Zo
+
Z2QKQjh0eklBUQotLS0gZ0tJVkJyK2F5c05lWm13YUVkeFBqYUZ3NXpZdnVYazhJ
+
anRldlplMmtMTQqd+cP8tjByVx/R+4LZMpMT3JlNBJTq3ySp6hP3mi1qsEVCc+zV
+
a9gGrT1MjBlsWdITMaXt1XYJtC2HTzDfTzSankFHvEVkzhF8uOe9A1vZbsqKCyFU
+
2uUGZzP32ugQ0ITY
+
-----END AGE ENCRYPTED FILE-----
+14
secrets/outline/smtp-password.age
···
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGN2U2dKQSB3VTM3
+
M3YwSG96U3I2Z1ZqQ0MrZXV5dzhFdTVNYXR6VzlRays5SElVTUZrCmpkdnc3anJY
+
NUFCOWpGZ2V6WWVVY0xuY2RGTVhqMlh1UUo2dGdKVEVHRmsKLT4gc3NoLWVkMjU1
+
MTkgMUNUOTd3IFNJaUpWSXc2K1I3bWkvYkNXNGdleXFTRlpZUTA4UC9tUlFqcmtT
+
dU9jU2sKSEI0TE83Rkw5U2QvZ3A4UlVWaWk5UWI1cktjNGVYaGJMeGtJOWZlYnJJ
+
bwotPiBzc2gtZWQyNTUxOSBlUDNUdFEgR3NMU3FGaFVpMldBZDNqaUlsdUU4SFFP
+
c1pCYnNDQzhmQ0JVTThGZVczdwpXQ2FJN3J2Y1BMUG8zNDBIV2JodVhpNlhOY1A3
+
RmNqOXZibG0wWXlHTk9nCi0+IEAnLWdyZWFzZSAmM3BpMTAvIEoibVlNIDdROTkp
+
VQp5aGdJYWlmb2Z6a0xBSmdpR0k1b1dkeWNCbmR4Tjg4TXh4bGlKaXVFaWVlSzkz
+
OWVRWlJYWmNhMDFwNDE1ZW10CjZrTWpGZUdyCi0tLSBQTG8vQllVZWlYZ3dZL1h6
+
UlNhVS91bThnWUUxK25GclErdlpoV3dJRklJCttr6JUh2OMxB3uo2bIZ3JXc4GcP
+
qZkFMVIchcr8M7ZVAL4Ia8vj9UuSnwjpJ0N/QajT4CM=
+
-----END AGE ENCRYPTED FILE-----
+14
secrets/outline/utils-secret.age
···
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGN2U2dKQSBFT1lD
+
bjVTaGcxdWNRSzgzbURWOHg0WnZmQ0t0eTRkVDlMUlBLNmlWZGtNCjhzSmJVYXRs
+
cER1NlV3MFVndEJEN1k0OGRBeXZaZ0t1VTRKby9KOU5oTk0KLT4gc3NoLWVkMjU1
+
MTkgMUNUOTd3IFJPclVNKzFlTUlUTGMyV1AyZEZyWERQbnRuOEM3dGpac0R6eWFo
+
Y29uaWcKWjBSN3RwUEtQQjBZbmJxeUl3Zy9TL05SM1FnK0hYSzBvQ2F1RVNRUUYv
+
VQotPiBzc2gtZWQyNTUxOSBlUDNUdFEgVVl4UDh5eTZscUlDN29YdXpWU2YzSWh6
+
QnhzSmZBM0lZaW1NWmVtU3BEawpBVGNhR1FFMURDKys1MUlkYVU4V1dtaGNVZk0x
+
QTgrdWs2TWFyeit1UWhzCi0+IFlwLWdyZWFzZSBfRC9sRSBUSChLIHhyNjFoXSA8
+
aGNLKC5ueQpXU3lIaUpscGk3M01tNHprUFM5Y3Q5SFE1V1FULzhlbW9WbwotLS0g
+
Z0tUS1lROGRURU5sSSt6djVCVHFpWFpiTDFKOGFKYzNpSVhMMEEzMFk0cwpxKFyy
+
wc8vAactgJ7M61dTI/4MtoBSI9JmY8ICoEqNYdBdnHyjX7qfbLDRxeFXMrUylUv2
+
Ny01hJCF4/epApwVU+d7LAbIlbRi6BxHCYK+SDgUgO4ZzvgHvNo2xk8+qUY0
+
-----END AGE ENCRYPTED FILE-----
+6
secrets/secrets.nix
···
"caddy.age".publicKeys = keys;
"glance.age".publicKeys = keys;
"lanyard.age".publicKeys = keys;
+
"minio.age".publicKeys = keys;
"ntfy.age".publicKeys = keys;
+
"outline/client-secret.age".publicKeys = keys;
+
"outline/minio-password.age".publicKeys = keys;
+
"outline/secret-key.age".publicKeys = keys;
+
"outline/smtp-password.age".publicKeys = keys;
+
"outline/utils-secret.age".publicKeys = keys;
}
-3
services/lanyard/default.nix
···
{ config, ... }:
{
-
# Redis service (new style)
services.redis.servers."lanyard" = {
enable = true;
port = 6379;
bind = "127.0.0.1";
};
-
# Age secret for Discord bot token
age.secrets.lanyard = {
file = ../../secrets/lanyard.age;
mode = "600";
};
-
# Lanyard Docker container
virtualisation.oci-containers.containers.lanyard = {
image = "phineas/lanyard:latest";
ports = [ "4001:4001" ];
+149
services/outline/default.nix
···
+
{ config, pkgs, ... }:
+
+
{
+
age.secrets = {
+
minioCredentials = {
+
file = ../../secrets/minio.age;
+
mode = "600";
+
owner = "minio";
+
group = "minio";
+
};
+
+
outlineClientSecret = {
+
file = ../../secrets/outline/client-secret.age;
+
mode = "600";
+
owner = "outline";
+
group = "outline";
+
};
+
outlineMinioSecret = {
+
file = ../../secrets/outline/minio-password.age;
+
mode = "600";
+
owner = "outline";
+
group = "outline";
+
};
+
outlineSecretKey = {
+
file = ../../secrets/outline/secret-key.age;
+
mode = "600";
+
owner = "outline";
+
group = "outline";
+
};
+
outlineSMTPPassword = {
+
file = ../../secrets/outline/smtp-password.age;
+
mode = "600";
+
owner = "outline";
+
group = "outline";
+
};
+
outlineUtilsSecret = {
+
file = ../../secrets/outline/utils-secret.age;
+
mode = "600";
+
owner = "outline";
+
group = "outline";
+
};
+
};
+
+
services.outline = {
+
enable = true;
+
publicUrl = "https://wiki.sappho.systems";
+
port = 3300;
+
forceHttps = true;
+
+
secretKeyFile = config.age.secrets.outlineSecretKey.path;
+
utilsSecretFile = config.age.secrets.outlineUtilsSecret.path;
+
+
databaseUrl = "postgres://outline:${builtins.readFile config.age.secrets.outlineSecretKey.path}@localhost/outline?sslmode=disable";
+
redisUrl = "redis://127.0.0.1:6380";
+
+
storage = {
+
storageType = "s3";
+
accessKey = "minio";
+
secretKeyFile = config.age.secrets.outlineMinioSecret.path;
+
uploadBucketUrl = "https://minio.sappho.systems";
+
uploadBucketName = "outline";
+
region = "us-east-1";
+
uploadMaxSize = 104857600;
+
importMaxSize = 104857600;
+
workspaceImportMaxSize = 104857600;
+
forcePathStyle = true;
+
acl = "private";
+
};
+
+
smtp = {
+
host = "smtp.purelymail.com";
+
port = 587;
+
username = "noreply@sapphic.moe";
+
passwordFile = config.age.secrets.outlineSMTPPassword.path;
+
fromEmail = "noreply@sapphic.moe";
+
secure = false;
+
};
+
+
oidcAuthentication = {
+
displayName = "Pocket ID";
+
+
clientId = "257b92c1-6b7f-41e9-a9c6-858a083295d8";
+
clientSecretFile = config.age.secrets.outlineClientSecret.path;
+
+
authUrl = "https://id.sappho.systems/authorize";
+
tokenUrl = "https://id.sappho.systems/api/oidc/token";
+
userinfoUrl = "https://id.sappho.systems/api/oidc/userinfo";
+
logoutUrl = "https://id.sappho.systems/api/oidc/end-session";
+
+
usernameClaim = "preferred_username";
+
scopes = [
+
"openid"
+
"profile"
+
"email"
+
"groups"
+
];
+
+
disableRedirect = true;
+
};
+
};
+
+
services.postgresql = {
+
enable = true;
+
package = pkgs.postgresql_15;
+
dataDir = "/var/lib/postgresql";
+
enableTCPIP = true;
+
ensureDatabases = [ "outline" ];
+
ensureUsers = [
+
{
+
name = "outline";
+
password = builtins.readFile config.age.secrets.outlineSecretKey.path;
+
}
+
];
+
authentication = pkgs.lib.mkOverride 10 ''
+
#type database DBuser origin-address auth-method
+
local all all trust
+
host all all 127.0.0.1/32 scram-sha-256
+
host all all ::1/128 scram-sha-256
+
'';
+
};
+
+
# Ensure Outline waits for Postgres
+
systemd.services.outline.requires = [ "postgresql.service" ];
+
services.redis.servers."outline" = {
+
enable = true;
+
port = 6380;
+
bind = "127.0.0.1";
+
};
+
+
services.minio = {
+
enable = true;
+
rootCredentialsFile = config.age.secrets.minioCredentials.path;
+
dataDir = "/var/lib/minio";
+
listenAddress = [
+
"0.0.0.0:9000"
+
"0.0.0.0:9001"
+
];
+
};
+
+
services.caddy.virtualHosts."wiki.sappho.systems" = {
+
extraConfig = ''
+
import common
+
import tls_cloudflare
+
reverse_proxy http://localhost:3300
+
'';
+
};
+
+
settings.firewall.allowedTCPPorts = [ 3300 ];
+
}