Compare commits

...

3 Commits

15 changed files with 584 additions and 2 deletions

7
.sops.yaml Normal file
View File

@ -0,0 +1,7 @@
keys:
- &v-th-ctr-01 age1cs2p7tgk9356tjmet6526k3ghwq9we82nz6z7qggqns656paku6sx30tkg
creation_rules:
- path_regex: secrets/secrets.yaml$
key_groups:
- age:
- *v-th-ctr-01

37
flake.lock generated
View File

@ -395,6 +395,22 @@
} }
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": {
"lastModified": 1744868846,
"narHash": "sha256-5RJTdUHDmj12Qsv7XOhuospjAjATNiTMElplWnJE9Hs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ebe4301cbd8f81c4f8d3244b3632338bbeb6d49c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1743703532, "lastModified": 1743703532,
"narHash": "sha256-s1KLDALEeqy+ttrvqV3jx9mBZEvmthQErTVOAzbjHZs=", "narHash": "sha256-s1KLDALEeqy+ttrvqV3jx9mBZEvmthQErTVOAzbjHZs=",
@ -421,6 +437,7 @@
"nixpkgs-stable" "nixpkgs-stable"
], ],
"nixpkgs-unstable": "nixpkgs-unstable", "nixpkgs-unstable": "nixpkgs-unstable",
"sops-nix": "sops-nix",
"stylix": "stylix" "stylix": "stylix"
} }
}, },
@ -445,6 +462,24 @@
"type": "github" "type": "github"
} }
}, },
"sops-nix": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1745310711,
"narHash": "sha256-ePyTpKEJTgX0gvgNQWd7tQYQ3glIkbqcW778RpHlqgA=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "5e3e92b16d6fdf9923425a8d4df7496b2434f39c",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
}
},
"stylix": { "stylix": {
"inputs": { "inputs": {
"base16": "base16", "base16": "base16",
@ -457,7 +492,7 @@
"git-hooks": "git-hooks", "git-hooks": "git-hooks",
"gnome-shell": "gnome-shell", "gnome-shell": "gnome-shell",
"home-manager": "home-manager_2", "home-manager": "home-manager_2",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_3",
"systems": "systems", "systems": "systems",
"tinted-foot": "tinted-foot", "tinted-foot": "tinted-foot",
"tinted-kitty": "tinted-kitty", "tinted-kitty": "tinted-kitty",

View File

@ -22,9 +22,11 @@
nixos-cosmic = { nixos-cosmic = {
url = "github:lilyinstarlight/nixos-cosmic"; url = "github:lilyinstarlight/nixos-cosmic";
}; };
sops-nix.url = "github:Mic92/sops-nix";
}; };
outputs = inputs@{ self, nixpkgs, nixpkgs-unstable, home-manager, nix-colors, stylix, nixos-cosmic, ... }: outputs = inputs@{ self, nixpkgs, nixpkgs-unstable, home-manager, nix-colors, stylix, nixos-cosmic, sops-nix, ... }:
let let
system = "x86_64-linux"; system = "x86_64-linux";
overlay-unstable = final: prev: { overlay-unstable = final: prev: {

View File

@ -68,6 +68,7 @@
isNormalUser = true; isNormalUser = true;
description = "Deploy"; description = "Deploy";
extraGroups = [ "networkmanager" "wheel" "dialout" ]; extraGroups = [ "networkmanager" "wheel" "dialout" ];
linger = true;
}; };
nix.settings.trusted-users = [ "root" "deploy" ]; nix.settings.trusted-users = [ "root" "deploy" ];

View File

@ -27,6 +27,7 @@
services.nextcloud-sync.enable = false; services.nextcloud-sync.enable = false;
services.podman.enable = true; services.podman.enable = true;
services.sops.enable = true;
theming.fonts.enable = false; theming.fonts.enable = false;
theming.stylix.enable = false; theming.stylix.enable = false;
@ -42,6 +43,12 @@
caddy.enable = true; caddy.enable = true;
kanidm.enable = true; kanidm.enable = true;
forgejo.enable = true; forgejo.enable = true;
immich.enable = true;
homepage.enable = true;
uptime-kuma.enable = true;
pingvin-share.enable = true;
vaultwarden.enable = true;
paperless-ngx.enable = true;
}; };
}; };

View File

@ -51,6 +51,43 @@ in {
handle @forgejo { handle @forgejo {
reverse_proxy forgejo:3000 reverse_proxy forgejo:3000
} }
@immich host photos.tbmrs.nl
handle @immich {
reverse_proxy immich-server:2283
}
@homepage host home.tbmrs.nl
handle @homepage {
reverse_proxy homepage:3000
}
@uptime-kuma host uptime.tbmrs.nl
handle @uptime-kuma {
reverse_proxy uptime-kuma:3001
}
@pingvin-share host share.tbmrs.nl
handle @pingvin-share {
reverse_proxy pingvin-share:3000
}
}
*.local.tbmrs.nl {
tls {
dns transip xeovalyte /etc/caddy/acme_key
resolvers 1.1.1.1
}
@vaultwarden host vault.local.tbmrs.nl
handle @vaultwarden {
reverse_proxy vaultwarden:80
}
@paperless-ngx host paperless.local.tbmrs.nl
handle @paperless-ngx {
reverse_proxy paperless-ngx:8000
}
} }
''; '';
}; };

View File

@ -0,0 +1,121 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.settings.containers.homepage;
in {
options = {
settings.containers.homepage.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable homepage container
'';
};
};
config = mkIf cfg.enable {
services.podman.containers.homepage = {
image = "ghcr.io/gethomepage/homepage:latest";
network = "proxy";
volumes = [
"%h/containers/homepage/config:/app/config"
"%h/containers/homepage/config/settings.yaml:/app/config/settings.yaml"
"%h/containers/homepage/config/services.yaml:/app/config/services.yaml"
"%h/containers/homepage/config/docker.yaml:/app/config/docker.yaml"
"/run/user/1000/podman/podman.sock:/var/run/podman.sock:ro"
];
environment = {
HOMEPAGE_ALLOWED_HOSTS = "home.tbmrs.nl";
};
};
home.file."containers/homepage/config/settings.yaml".source = (pkgs.formats.yaml { }).generate "settings" {
title = "Timo's Server";
description = "server from Timo";
theme = "dark";
color = "slate";
};
home.file."containers/homepage/config/services.yaml".source = (pkgs.formats.yaml { }).generate "services" [
{
"Infra" = [
{
"Kanidm" = {
href = "https://auth.tbmrs.nl";
description = "Oauth2 and ldap provider";
icon = "kanidm";
server = "podman";
container = "kanidm";
};
}
{
"Uptime Kuma" = {
href = "https://uptime.tbmrs.nl";
description = "Uptime and status";
icon = "uptime-kuma";
server = "podman";
container = "uptime-kuma";
};
}
];
}
{
"Services" = [
{
"Forgejo" = {
href = "https://git.tbmrs.nl";
description = "Git server";
icon = "forgejo";
server = "podman";
container = "forgejo";
};
}
{
"Immich" = {
href = "https://photos.tbmrs.nl";
description = "Photo's and videos";
icon = "immich";
server = "podman";
container = "immich-server";
};
}
{
"Pingvin" = {
href = "https://share.tbmrs.nl";
description = "File sharing";
icon = "pingvin-share";
server = "podman";
container = "pingvin-share";
};
}
{
"Vaultwarden" = {
href = "https://vault.local.tbmrs.nl";
description = "Password management";
icon = "vaultwarden";
server = "podman";
container = "vaultwarden";
};
}
{
"Paperless" = {
href = "https://paperless.local.tbmrs.nl";
description = "Documents management";
icon = "paperless-ngx";
server = "podman";
container = "paperless-ngx";
};
}
];
}
];
home.file."containers/homepage/config/docker.yaml".source = (pkgs.formats.yaml {}).generate "docker" {
podman = {
socket = "/var/run/podman.sock";
};
};
};
}

View File

@ -0,0 +1,75 @@
{ config, lib, ... }:
with lib;
let
cfg = config.settings.containers.immich;
in {
options = {
settings.containers.immich.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable immich container
'';
};
};
config = mkIf cfg.enable {
services.podman.containers.immich-server = {
image = "ghcr.io/immich-app/immich-server:release";
network = "proxy";
volumes = [
"%h/containers/immich/upload:/usr/src/app/upload"
"/etc/localtime:/etc/localtime:ro"
];
extraConfig = {
Unit = {
After = [
"podman-immich-redis.service"
"podman-immich-database.service"
];
Requires = [
"podman-immich-redis.service"
"podman-immich-database.service"
];
};
};
environment = {
DB_PASSWORD = "changeme";
DB_USERNAME = "postgres";
DB_DATABASE_NAME = "immich";
DB_HOSTNAME = "immich-database";
REDIS_HOSTNAME = "immich-redis";
};
};
services.podman.containers.immich-machine-learning = {
image = "ghcr.io/immich-app/immich-machine-learning:release";
network = "proxy";
volumes = [
"%h/containers/immich/model-cache:/cache"
];
};
services.podman.containers.immich-redis = {
image = "docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1";
network = "proxy";
};
services.podman.containers.immich-database = {
image = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52";
network = "proxy";
volumes = [
"%h/containers/immich/database-data:/var/lib/postgresql/data"
];
environment = {
POSTGRES_PASSWORD = "changeme";
POSTGRES_USER = "postgres";
POSTGRES_DB = "immich";
POSTGRES_INITDB_ARGS = "--data-checksums";
};
exec = ''postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on'';
};
};
}

View File

@ -0,0 +1,97 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.settings.containers.paperless-ngx;
in {
options = {
settings.containers.paperless-ngx.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable Paperless NGX container
'';
};
};
config = mkIf cfg.enable {
settings.services.sops.enable = true;
services.podman.containers.paperless-ngx = {
image = "ghcr.io/paperless-ngx/paperless-ngx:latest";
network = "proxy";
volumes = [
"%h/containers/paperless-ngx/data:/usr/src/paperless/data"
"%h/containers/paperless-ngx/media:/usr/src/paperless/media"
"%h/containers/paperless-ngx/export:/usr/src/paperless/export"
"%h/containers/paperless-ngx/consume:/usr/src/paperless/consume"
"${config.sops.secrets."containers/paperless-ngx/db-password".path}:/run/secrets/db-password"
"${config.sops.secrets."containers/paperless-ngx/secret".path}:/run/secrets/secret"
"${config.sops.secrets."containers/paperless-ngx/openid-providers".path}:/run/secrets/openid-providers"
];
environment = {
PAPERLESS_REDIS = "redis://paperless-ngx-broker:6379";
PAPERLESS_DBHOST = "paperless-ngx-db";
PAPERLESS_URL = "https://paperless.local.tbmrs.nl";
PAPERLESS_DBPASS_FILE = "/run/secrets/db-password";
PAPERLESS_SECRET_KEY_FILE = "/run/secrets/secret";
PAPERLESS_DISABLE_REGULAR_LOGIN = false;
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
PAPERLESS_SOCIALACCOUNT_PROVIDERS_FILE = "/run/secrets/openid-providers";
PAPERLESS_SOCIAL_ACCOUNT_SYNC_GROUPS = true;
};
extraConfig = {
Unit = {
After = [
"sops-nix.service"
"podman-paperless-ngx-db.service"
"podman-paperless-ngx-broker.service"
];
Requires = [
"podman-paperless-ngx-db.service"
"podman-paperless-ngx-broker.service"
];
};
};
};
services.podman.containers.paperless-ngx-db = {
image = "docker.io/library/postgres:17";
network = "proxy";
volumes = [
"%h/containers/paperless-ngx/db-data:/var/lib/postgresql/data"
"${config.sops.secrets."containers/paperless-ngx/db-password".path}:/run/secrets/db-password"
];
environment = {
POSTGRES_DB = "paperless";
POSTGRES_USER = "paperless";
POSTGRES_PASSWORD_FILE = "/run/secrets/db-password";
};
extraConfig = {
Unit = {
After = [
"sops-nix.service"
];
};
};
};
services.podman.containers.paperless-ngx-broker = {
image = "docker.io/library/redis:7";
network = "proxy";
volumes = [
"%h/containers/paperless-ngx/redis-data:/data"
];
};
sops.secrets = {
"containers/paperless-ngx/db-password" = { };
"containers/paperless-ngx/secret" = { };
"containers/paperless-ngx/openid-providers" = { };
};
};
}

View File

@ -0,0 +1,73 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.settings.containers.pingvin-share;
in {
options = {
settings.containers.pingvin-share.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable Pingvin share container
'';
};
};
config = mkIf cfg.enable {
settings.services.sops.enable = true;
services.podman.containers.pingvin-share = {
image = "ghcr.io/stonith404/pingvin-share";
network = "proxy";
volumes = [
"%h/containers/pingvin-share/data:/opt/app/backend/data"
# "%h/containers/pingvin-share/config.yaml:/opt/app/config.yaml"
"${config.sops.templates."container-pingvin.yaml".path}:/opt/app/config.yaml"
];
environment = {
TRUST_PROXY = true;
};
userNS = "keep-id";
extraConfig = {
Unit = {
After = [
"sops-nix.service"
];
};
};
};
sops.templates = {
"container-pingvin.yaml" = {
content = /*yaml*/ ''
general:
secureCookies: "true"
appUrl: https://share.tbmrs.nl
showHomePage: "false"
share:
allowRegistration: "true"
maxSize: "10000000000"
oauth:
disablePassword: "false"
oidc-enabled: "true"
oidc-discoveryUri: "https://auth.tbmrs.nl/oauth2/openid/pingvin/.well-known/openid-configuration"
oidc-clientId: pingvin
oidc-clientSecret: "${config.sops.placeholder."containers/pingvin-share/oidc-secret"}"
initUser:
enabled: "true"
username: "admin"
email: "admin@example.com"
password: "my-secure-password"
isAdmin: true
ldapDN: ""
'';
};
};
sops.secrets = {
"containers/pingvin-share/oidc-secret" = { };
};
};
}

View File

@ -0,0 +1,27 @@
{ config, lib, ... }:
with lib;
let
cfg = config.settings.containers.uptime-kuma;
in {
options = {
settings.containers.uptime-kuma.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable uptime kuma container
'';
};
};
config = mkIf cfg.enable {
services.podman.containers.uptime-kuma = {
image = "louislam/uptime-kuma:1";
network = "proxy";
volumes = [
"%h/containers/uptime-kuma/data:/app/data"
];
};
};
}

View File

@ -0,0 +1,31 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.settings.containers.vaultwarden;
in {
options = {
settings.containers.vaultwarden.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable Vaultwarden container
'';
};
};
config = mkIf cfg.enable {
services.podman.containers.vaultwarden = {
image = "ghcr.io/dani-garcia/vaultwarden:latest";
network = "proxy";
volumes = [
"%h/containers/vaultwarden/data:/data"
];
environment = {
DOMAIN = "https://vault.local.tbmrs.nl";
SIGNUPS_ALLOWED = true;
};
};
};
}

View File

@ -16,6 +16,7 @@
./services/nextcloud.nix ./services/nextcloud.nix
./services/podman.nix ./services/podman.nix
./services/sops.nix
./theming/fonts.nix ./theming/fonts.nix
./theming/stylix.nix ./theming/stylix.nix
@ -28,5 +29,11 @@
./containers/kanidm.nix ./containers/kanidm.nix
./containers/nginx.nix ./containers/nginx.nix
./containers/forgejo.nix ./containers/forgejo.nix
./containers/immich.nix
./containers/homepage.nix
./containers/uptime-kuma.nix
./containers/pingvin-share.nix
./containers/vaultwarden.nix
./containers/paperless-ngx.nix
]; ];
} }

View File

@ -0,0 +1,34 @@
{ lib, config, inputs, pkgs, ... }:
with lib;
let
cfg = config.settings.services.sops;
in {
options = {
settings.services.sops.enable = lib.mkOption {
type = lib.types.bool;
description = ''
Enable sops secret management
'';
default = false;
};
};
imports = [
inputs.sops-nix.homeManagerModules.sops
];
config = mkIf cfg.enable {
home.packages = with pkgs; [
sops
age
];
sops = {
age.keyFile = "/home/${config.home.username}/.config/sops/age/keys.txt"; # must have no password!
defaultSopsFile = ../../../secrets/deploy.yaml;
};
};
}

28
secrets/deploy.yaml Normal file
View File

@ -0,0 +1,28 @@
example-key: ENC[AES256_GCM,data:zQ4Sb+IOxM/JB/0KZQ==,iv:SgpzREfqbgBgd8psV7Optl4nDpMmDBDsitGQZLLSAL0=,tag:mZ48ExMkupiuMqJvgoIK+g==,type:str]
containers:
pingvin-share:
oidc-secret: ENC[AES256_GCM,data:jO5fvIK/1XnFweqKvedPMED0xvsqErjDP+eT7wAwXFuREbS6KakwY7pUzi20wdI0,iv:SnnmXiZoawpZV83483esQ1TIaFTACiIUcA6hcoXsw0I=,tag:cC/ftyj8jlK1re/rX4IiEw==,type:str]
paperless-ngx:
db-password: ENC[AES256_GCM,data:H21HVshmFuWJ5qNIrjm0VMGHEsT7cCvScgamU+CAaNZ6j5ux/r4xiF9zP7Qh40sKTOvyoWGTcHGPHE5ClpGuQA==,iv:tDIRfThBOfHr+gGRqywlHAk/x4MkhHRFsJEp5nnlGPA=,tag:XbYKD90l3u93Ur4VOqOn6w==,type:str]
secret: ENC[AES256_GCM,data:+1hriBiSbt+zUjEkBTEM90PFNlxfNwRAmz8wHyeyOnq6ThI+PtlDu83sunBFL2FUYJX0N4h3R4FvJBUkrPr0NQ==,iv:zzhFaoLnskspp1S291KABLZITgcof63cjShnsZrlAmw=,tag:+aafTLgZVBWeclQLQvVlQg==,type:str]
openid-providers: ENC[AES256_GCM,data:bpUnVFvvMUTkjApqkWi8gcVXgvaM8d/bcuoiQgco/UJZBQqbSEQys8BSb9yaSx8HAIZEcWjpb4N5FEb3P1uH8de4Nq7nlAg+GdDuS4WjInF5KOWQY9p0T4HfnMJyfx7zIiWW7nPSaxPNtMNZxQiXnW8oJr1fmz/O49T4egw1tdxWj6CO4d+T6aRKBsS26Ie1HYJ6BTT1B6qiIgiBpAvXh558nduk3tIz1blTCeV9XpnZgKlj45mS+g6+Eqqj0ATI7CC5y5CEVaMs1rC0NzlVm7/rEV4dBpVlmHtN5KE4aRMiH3YUYnJ5Nbo7EVfPQ7xkEPRmIOtXzXut8Hpml3QkFhdvHH5ZbworFrwL+LHm4GpHbUyCGc6OkWZ9+/mILos3o4BaI0qLQRchoGddvx5dOJyn5lJj3AfRgLB8zu9JSXZDre/LHovcJwpzmOip09mmjk7CGjea2f8wDnnX2HRXlM9alUbwlvXU69+MhTJBmqWe4kCBB8riz5gHRg2lQRMnMg64roPv7C7B1VoHANISDA3LHG4hocXknO69rBnjTjIYJNblDEtTztSTJdQvYb2102gFrxg4Grxu6/gQcXTbe4DScqUmIhebk98Nc7xlca9l+FGzmFB8cbznFFiaLE3wRK3G7g540+GOPoyXXxTGp3l5cOi6VE8cDd+HK5KDBnlgFecR/5QCRw40e9qvmCSttaxDCme+YrFHW248jgVwWvsNiFT5bBR4phS5c0VjrHdcy+1zY3R6GsnmXMfonIYHcq8apMhqVCdqHAzV2Qij4/RIyqCQoOeX86fi/pdDCvtMEbYt2nVqITmmxgOFRk4GSbLcjkbKG0SPVQWjGGXNkB/MfhUsvHG7E00IrAt1DgFEzqSar4Ildd7D4MzURJZxWNqoES0IhyVcxOgweCTakXM9QHqt,iv:ba2bri2F/B6Sp3HfpXVWZ/WMVFOPF4+DyAtdS56yNqQ=,tag:1uW6iDXiZm0vXUjmJPBchw==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1cs2p7tgk9356tjmet6526k3ghwq9we82nz6z7qggqns656paku6sx30tkg
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkZ3BnZ3JoT3l2RmQrSzJV
aUk4MEV1aUxKUXBhLyt4T1FBT0pyWTdxYmpFCkdlMm9qYUxtR0UvblhJSlVaMno4
NGtUcVZSaUprZ2lEeVpPaUFNcGlxSFUKLS0tIEcydm1tR0xxM2JpYzZBblBXSUZF
bGpsMnpoQWlxbmlobVdVSjU2ZWp1dGMKql+6ZqtuixZ9TJgJMaTOFsB0gsLLvuqE
ZQikUHunrP8d5n/TvzL4VyIF2Oqy+cjTnjX/9fcqsjB6w3oY4qDXkg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-04-30T09:15:42Z"
mac: ENC[AES256_GCM,data:Mxq3LnXRpnVv/U7QEGL5I3gF3y8W8IfsdTvinIsn5Qi6m04JinyJ0Vgr4JbMstB/8gh259MsAO2na7/vZ8brLuol0X8vZeIlgIoX8DazuI6dpNr284zPWsiRNr8gzBViYDRb4GVf+GF11iXcw3UlJE8uB+N4z4Y4sUbobOt402c=,iv:G86XwJp6ZRB8ioDbNDGKxLPNIcAmcusH/blT/8FKFlk=,tag:emMQZ7TAJGy7yqSpD7+1Cg==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.4