[Focalboard] Sets up Focalboard with storage, database and secrets. [OpenProject] Removes the container
This commit is contained in:
@@ -4,6 +4,8 @@ bookstack_db: ENC[AES256_GCM,data:m8fGgAfmJu1rEaxmTVH4FfBhyiU=,iv:OnBT/6sp9zmcJ1
|
|||||||
mariadb_root_password: ENC[AES256_GCM,data:p965ZhFQqqX+Ub1yhgklVYlBH6A=,iv:qC5WwTvZGvlbAkYiv35xHizMYAnP0V0Vw79EkvL32wQ=,tag:gOJQvHeOC9turFKOMQ9DNg==,type:str]
|
mariadb_root_password: ENC[AES256_GCM,data:p965ZhFQqqX+Ub1yhgklVYlBH6A=,iv:qC5WwTvZGvlbAkYiv35xHizMYAnP0V0Vw79EkvL32wQ=,tag:gOJQvHeOC9turFKOMQ9DNg==,type:str]
|
||||||
openproject:
|
openproject:
|
||||||
secret-key-base: ENC[AES256_GCM,data:luTuUtxL/SGx6O10y9cRiAzJHw==,iv:8qVJm+obsHr9eV0h+jdpsreeFGxEM+UFZHHiIUUPs6w=,tag:+zpjhKoIiNNSSYxe1QkQ7Q==,type:str]
|
secret-key-base: ENC[AES256_GCM,data:luTuUtxL/SGx6O10y9cRiAzJHw==,iv:8qVJm+obsHr9eV0h+jdpsreeFGxEM+UFZHHiIUUPs6w=,tag:+zpjhKoIiNNSSYxe1QkQ7Q==,type:str]
|
||||||
|
focalboard:
|
||||||
|
database: ENC[AES256_GCM,data:GDxYdkVV+tl3qHxWMMoetmMnLnY=,iv:JujgNPyUEHCmD/yW3UKCTj9GTk9a7EkvUiyFLF4sF8A=,tag:46YZ7AthpiiaX69aN9a3Bg==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
@@ -28,8 +30,8 @@ sops:
|
|||||||
by9aNFY4dXNxaWxnTXFTQS9reHhuQWMKh5rZ93nFtBV9EpFVRp+E+GXZ6xzVy2Jw
|
by9aNFY4dXNxaWxnTXFTQS9reHhuQWMKh5rZ93nFtBV9EpFVRp+E+GXZ6xzVy2Jw
|
||||||
vFh4deGcAb60q4odSaeWfk1Dr7L9Ua69oK9omjbCNUt+P7Kwlfca7Q==
|
vFh4deGcAb60q4odSaeWfk1Dr7L9Ua69oK9omjbCNUt+P7Kwlfca7Q==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-04-03T19:04:17Z"
|
lastmodified: "2025-04-21T19:34:54Z"
|
||||||
mac: ENC[AES256_GCM,data:DEUuXrCl3OXJ9NbfLoxHIND5+m7enHNDbuLE2jS8nvZCpKm83YoXwp0RhIFA725wJnBej26HLkovCi7V/4s5NrrfT9sPHGNBMSHB0AAcwu3Dmo6G2PBKvAWZTxXmiIXGx8vSvWNbLrp3vTV8jjTpfbuMvOiuxayKfn6esKI9T2o=,iv:zUfbL753Uvzg6WW4kwI8swmpWHIQ/IpCyYSsLptVDG4=,tag:XZy8jNZYYcqspd6zptH3pQ==,type:str]
|
mac: ENC[AES256_GCM,data:D44YsnrRpYQmJxAjXdap+Ya6iqPrhdEmiaTgUOM53JYmkihIvmMxm3b09xMxucv3B7tvi5vCfcllgij+RZ2RPnQDFg8ZzYQu7AQSG8rgwoh3E9Zijx2gQm59hhvJlca2cB710hUL87Tkdbvz26LZevIf5gP83u2JCkXLzr9O/Ew=,iv:lMthECFXzbao4bVVK9eJgK5ubu1NUg97BI2T9OqlICw=,tag:8t+2kPoqKeSKF8e+x5dtmg==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.9.4
|
version: 3.9.4
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
# Additional configuration
|
# Additional configuration
|
||||||
imports = [
|
imports = [
|
||||||
./containers/bookstack.nix
|
./containers/bookstack.nix
|
||||||
|
./containers/focalboard.nix
|
||||||
./containers/gitea.nix
|
./containers/gitea.nix
|
||||||
./containers/grafana.nix
|
./containers/grafana.nix
|
||||||
./containers/jobhunt.nix
|
./containers/jobhunt.nix
|
||||||
./containers/mariadb.nix
|
./containers/mariadb.nix
|
||||||
./containers/nextcloud.nix
|
./containers/nextcloud.nix
|
||||||
./containers/openproject.nix
|
|
||||||
./containers/prometheus.nix
|
./containers/prometheus.nix
|
||||||
./containers/pocket-id.nix
|
./containers/pocket-id.nix
|
||||||
./containers/public-homepage.nix
|
./containers/public-homepage.nix
|
||||||
|
|||||||
74
system/hosts/mcp/containers/focalboard.nix
Normal file
74
system/hosts/mcp/containers/focalboard.nix
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
let
|
||||||
|
inherit (import ./lib.nix config) mkContainer mkPostgresContainer terakoda;
|
||||||
|
userIds = import ./user-ids.nix;
|
||||||
|
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
(mkPostgresContainer {
|
||||||
|
name = "focalboard";
|
||||||
|
directory = "/tank/focalboard/db";
|
||||||
|
uid = userIds.focalboard.uid;
|
||||||
|
gid = userIds.focalboard.gid;
|
||||||
|
passwordSecret = "focalboard/database";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
users.groups.focalboard = {
|
||||||
|
gid = userIds.focalboard.gid;
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.focalboard = {
|
||||||
|
uid = userIds.focalboard.uid;
|
||||||
|
isSystemUser = true;
|
||||||
|
description = "System User for Focalboard";
|
||||||
|
group = "focalboard";
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets = {
|
||||||
|
"focalboard/database" = {
|
||||||
|
restartUnits = [ "podman-focalboard.service" "podman-focalboard-postgres.service" ];
|
||||||
|
mode = "0400";
|
||||||
|
owner = config.users.users.focalboard.name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.templates."focalboard-config.json" = {
|
||||||
|
restartUnits = [ "podman-focalboard.service" ];
|
||||||
|
owner = config.users.users.focalboard.name;
|
||||||
|
content = builtins.toJSON {
|
||||||
|
# Defaults from https://github.com/mattermost-community/focalboard/blob/main/config.json
|
||||||
|
"serverRoot" = "https://focalboard.terakoda.com";
|
||||||
|
"port" = 8000;
|
||||||
|
"dbtype" = "postgres";
|
||||||
|
"dbconfig" = "postgres://focalboard:${config.sops.placeholder."focalboard/database"}@focalboard-postgres/focalboard?sslmode=disable&connect_timeout=10";
|
||||||
|
"useSSL" = true;
|
||||||
|
"prometheus_address" = ":9092";
|
||||||
|
"session_expire_time" = 2592000;
|
||||||
|
"session_refresh_time" = 18000;
|
||||||
|
"postgres_dbconfig" = "dbname=focalboard sslmode=disable";
|
||||||
|
"webpath" = "./pack";
|
||||||
|
"filespath" = "./data/files";
|
||||||
|
"telemetry" = true;
|
||||||
|
"prometheusaddress" = ":9092";
|
||||||
|
"enableLocalMode" = true;
|
||||||
|
"localModeSocketLocation" = "/var/tmp/focalboard_local.socket";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.oci-containers.containers = {
|
||||||
|
focalboard = mkContainer {
|
||||||
|
image = "mattermost/focalboard";
|
||||||
|
hostName = "focalboard";
|
||||||
|
domain = terakoda;
|
||||||
|
dependsOn = [ "focalboard-postgres" ];
|
||||||
|
port = 8000;
|
||||||
|
user = "${toString userIds.focalboard.uid}:${toString userIds.focalboard.gid}";
|
||||||
|
volumes = [
|
||||||
|
"/tank/focalboard/data/files:/opt/focalboard/data/files"
|
||||||
|
"${config.sops.templates."focalboard-config.json".path}:/opt/focalboard/config.json:ro"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ config:
|
|||||||
let
|
let
|
||||||
havenisms = "havenisms.com";
|
havenisms = "havenisms.com";
|
||||||
blazestar = "blazestar.net";
|
blazestar = "blazestar.net";
|
||||||
|
terakoda = "terakoda.com";
|
||||||
|
terakoda_net = "terakoda.net";
|
||||||
hostRule = host: domain: "Host(`${host}.${domain}`)";
|
hostRule = host: domain: "Host(`${host}.${domain}`)";
|
||||||
hostRuleHavenisms = host: hostRule host havenisms;
|
hostRuleHavenisms = host: hostRule host havenisms;
|
||||||
localNet = "192.168.0.0/16";
|
localNet = "192.168.0.0/16";
|
||||||
@@ -18,46 +20,42 @@ in
|
|||||||
localHostRuleHavenisms
|
localHostRuleHavenisms
|
||||||
havenisms
|
havenisms
|
||||||
blazestar
|
blazestar
|
||||||
;
|
terakoda
|
||||||
|
terakoda_net;
|
||||||
|
|
||||||
mkContainer =
|
mkContainer = {
|
||||||
{
|
|
||||||
image,
|
image,
|
||||||
hostName,
|
hostName,
|
||||||
port,
|
port,
|
||||||
homepageOpts,
|
homepageOpts ? {},
|
||||||
dependsOn ? [ ],
|
dependsOn ? [],
|
||||||
domain ? havenisms,
|
domain ? havenisms,
|
||||||
ports ? [ ],
|
ports ? [],
|
||||||
volumes ? [ ],
|
volumes ? [],
|
||||||
environment ? { },
|
environment ? {},
|
||||||
environmentFiles ? [ ],
|
environmentFiles ? [],
|
||||||
public ? false,
|
public ? false,
|
||||||
|
user ? null,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
routerRule = if public then hostRule hostName domain else localHostRule hostName domain;
|
routerRule = if public then hostRule hostName domain else localHostRule hostName domain;
|
||||||
|
homepageLabels = if homepageOpts == {} then {} else {
|
||||||
|
"homepage.group" = "${homepageOpts.group}";
|
||||||
|
"homepage.name" = "${homepageOpts.name}";
|
||||||
|
"homepage.icon" = "${homepageOpts.icon}";
|
||||||
|
"homepage.href" = "https://${hostName}.${domain}";
|
||||||
|
"homepage.description" = "${homepageOpts.description}";
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit
|
inherit image dependsOn volumes environment environmentFiles ports user;
|
||||||
image
|
|
||||||
dependsOn
|
|
||||||
volumes
|
|
||||||
environment
|
|
||||||
environmentFiles
|
|
||||||
ports
|
|
||||||
;
|
|
||||||
hostname = "${hostName}.${domain}";
|
hostname = "${hostName}.${domain}";
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
extraOptions = [
|
labels = {
|
||||||
"-l=traefik.enable=true"
|
"traefik.enable" = "true";
|
||||||
"-l=traefik.http.routers.${hostName}.rule=${routerRule}"
|
"traefik.http.routers.${hostName}.rule" = "${routerRule}";
|
||||||
"-l=traefik.http.services.${hostName}.loadbalancer.server.port=${toString port}"
|
"traefik.http.services.${hostName}.loadbalancer.server.port" = "${toString port}";
|
||||||
"-l=homepage.group=${homepageOpts.group}"
|
} // homepageLabels;
|
||||||
"-l=homepage.name=${homepageOpts.name}"
|
|
||||||
"-l=homepage.icon=${homepageOpts.icon}"
|
|
||||||
"-l=homepage.href=https://${hostName}.${domain}"
|
|
||||||
"-l=homepage.description=${homepageOpts.description}"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Creates a MariaDB container for a specific app. It should be safe to give
|
# Creates a MariaDB container for a specific app. It should be safe to give
|
||||||
@@ -66,8 +64,7 @@ in
|
|||||||
# user.
|
# user.
|
||||||
#
|
#
|
||||||
# Note that this returns a _module_ so that it can be imported and provide many different config values.
|
# Note that this returns a _module_ so that it can be imported and provide many different config values.
|
||||||
mkMariaDbContainer =
|
mkMariaDbContainer = {
|
||||||
{
|
|
||||||
name,
|
name,
|
||||||
uid,
|
uid,
|
||||||
gid,
|
gid,
|
||||||
@@ -95,4 +92,32 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mkPostgresContainer = {
|
||||||
|
name,
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
passwordSecret,
|
||||||
|
directory,
|
||||||
|
containerName ? "${name}-postgres",
|
||||||
|
databaseName ? name,
|
||||||
|
username ? name,
|
||||||
|
}: { config, ... }: {
|
||||||
|
virtualisation.oci-containers.containers."${containerName}" = {
|
||||||
|
image = "postgres";
|
||||||
|
autoStart = true;
|
||||||
|
volumes = [
|
||||||
|
# Note that data must be mounted at this location to persist.
|
||||||
|
# See https://github.com/docker-library/docs/blob/master/postgres/README.md#pgdata
|
||||||
|
"${directory}:/var/lib/postgresql/data"
|
||||||
|
"${config.sops.secrets."${passwordSecret}".path}:/run/secrets/postgres_password"
|
||||||
|
];
|
||||||
|
user = "${toString uid}:${toString gid}";
|
||||||
|
environment = {
|
||||||
|
POSTGRES_USER = username;
|
||||||
|
POSTGRES_DB = databaseName;
|
||||||
|
POSTGRES_PASSWORD_FILE = "/run/secrets/postgres_password";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,8 @@
|
|||||||
uid = 2005;
|
uid = 2005;
|
||||||
gid = 2005;
|
gid = 2005;
|
||||||
};
|
};
|
||||||
|
focalboard = {
|
||||||
|
uid = 2006;
|
||||||
|
gid = 2006;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user