Separete container and proxy config
This commit is contained in:
parent
84d2323250
commit
782b3ef4bf
9 changed files with 579 additions and 543 deletions
517
hosts/nixos/hs/containers.nix
Normal file
517
hosts/nixos/hs/containers.nix
Normal file
|
|
@ -0,0 +1,517 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
# Import Immich configuration from declarative config file
|
||||||
|
immichConfig = import ../../../config/immich.nix;
|
||||||
|
|
||||||
|
# Convert Nix configuration to JSON string
|
||||||
|
immichConfigJson = builtins.toJSON immichConfig;
|
||||||
|
|
||||||
|
# Write config file to a location accessible by the container
|
||||||
|
immichConfigFile = pkgs.writeText "immich.json" immichConfigJson;
|
||||||
|
|
||||||
|
# Universal container configuration
|
||||||
|
commonUID = "1000";
|
||||||
|
commonGID = "100";
|
||||||
|
systemTZ = config.time.timeZone;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Container definitions for hs host
|
||||||
|
virtualisation.oci-containers.containers = {
|
||||||
|
homeassistant = {
|
||||||
|
image = "ghcr.io/home-assistant/home-assistant:stable";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/home/config:/config"
|
||||||
|
"/etc/localtime:/etc/localtime:ro"
|
||||||
|
"/run/dbus:/run/dbus:ro"
|
||||||
|
# Mount declarative configuration files
|
||||||
|
"/home/yanlin/.config/nix/config/homeassistant/configuration.yaml:/config/configuration.yaml:ro"
|
||||||
|
"/home/yanlin/.config/nix/config/homeassistant/automations.yaml:/config/automations.yaml:ro"
|
||||||
|
"/home/yanlin/.config/nix/config/homeassistant/scenes.yaml:/config/scenes.yaml:ro"
|
||||||
|
"/home/yanlin/.config/nix/config/homeassistant/scripts.yaml:/config/scripts.yaml:ro"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.homeassistant.rule" = "Host(`home.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.homeassistant.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.homeassistant.tls" = "true";
|
||||||
|
"traefik.http.routers.homeassistant.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.homeassistant.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.homeassistant.loadbalancer.server.port" = "8123";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
TZ = systemTZ;
|
||||||
|
# Configure Home Assistant to trust reverse proxy
|
||||||
|
HASS_HTTP_TRUSTED_PROXY_1 = "127.0.0.1";
|
||||||
|
HASS_HTTP_TRUSTED_PROXY_2 = "::1";
|
||||||
|
HASS_HTTP_USE_X_FORWARDED_FOR = "true";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--privileged" # Required for USB device access
|
||||||
|
"--network=host" # Use host networking
|
||||||
|
"--device=/dev/ttyUSB0:/dev/ttyUSB0" # Sky Connect Zigbee dongle
|
||||||
|
"--device=/dev/dri:/dev/dri" # Hardware acceleration
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Immich photo and video backup system
|
||||||
|
immich = {
|
||||||
|
image = "ghcr.io/imagegenius/immich:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/immich/config:/config"
|
||||||
|
"/mnt/storage/appbulk/immich:/photos"
|
||||||
|
"/mnt/storage/Media/DCIM:/libraries"
|
||||||
|
# Mount the declarative config file
|
||||||
|
"${immichConfigFile}:/config/immich.json:ro"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.immich.rule" = "Host(`photo.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.immich.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.immich.tls" = "true";
|
||||||
|
"traefik.http.routers.immich.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.immich.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.immich.loadbalancer.server.port" = "8080";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
# Point to the mounted config file
|
||||||
|
IMMICH_CONFIG_FILE = "/config/immich.json";
|
||||||
|
# Database connection (keep as env vars for security)
|
||||||
|
DB_HOSTNAME = "immich-db";
|
||||||
|
DB_USERNAME = "postgres";
|
||||||
|
DB_PASSWORD = "postgres";
|
||||||
|
DB_DATABASE_NAME = "postgres";
|
||||||
|
DB_PORT = "5432";
|
||||||
|
# Redis connection
|
||||||
|
REDIS_HOSTNAME = "immich-redis";
|
||||||
|
REDIS_PORT = "6379";
|
||||||
|
# Machine Learning server (internal)
|
||||||
|
MACHINE_LEARNING_HOST = "0.0.0.0";
|
||||||
|
MACHINE_LEARNING_PORT = "3003";
|
||||||
|
MACHINE_LEARNING_WORKERS = "1";
|
||||||
|
MACHINE_LEARNING_WORKER_TIMEOUT = "120";
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = [
|
||||||
|
"5000:8080"
|
||||||
|
];
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
"--device=/dev/dri:/dev/dri" # Hardware acceleration
|
||||||
|
];
|
||||||
|
|
||||||
|
dependsOn = [ "immich-db" "immich-redis" ];
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# PostgreSQL database for Immich with vector extension
|
||||||
|
immich-db = {
|
||||||
|
image = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/immich/db:/var/lib/postgresql/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
POSTGRES_PASSWORD = "postgres";
|
||||||
|
POSTGRES_USER = "postgres";
|
||||||
|
POSTGRES_DB = "postgres";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Redis cache for Immich
|
||||||
|
immich-redis = {
|
||||||
|
image = "docker.io/redis:7.2-alpine";
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Plex Media Server
|
||||||
|
plex = {
|
||||||
|
image = "docker.io/linuxserver/plex:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/plex/config:/config"
|
||||||
|
"/mnt/storage/appbulk/plex-transcode:/transcode"
|
||||||
|
"/mnt/storage/Media:/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.plex.rule" = "Host(`plex.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.plex.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.plex.tls" = "true";
|
||||||
|
"traefik.http.routers.plex.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.plex.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.plex.loadbalancer.server.port" = "32400";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
VERSION = "docker";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
"--device=/dev/dri:/dev/dri" # Hardware acceleration
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Sonarr TV show management
|
||||||
|
sonarr = {
|
||||||
|
image = "docker.io/linuxserver/sonarr:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/sonarr/config:/config"
|
||||||
|
"/mnt/storage/Media:/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.sonarr.rule" = "Host(`sonarr.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.sonarr.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.sonarr.tls" = "true";
|
||||||
|
"traefik.http.routers.sonarr.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.sonarr.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.sonarr.loadbalancer.server.port" = "8989";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Radarr movie management
|
||||||
|
radarr = {
|
||||||
|
image = "docker.io/linuxserver/radarr:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/radarr/config:/config"
|
||||||
|
"/mnt/storage/Media:/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.radarr.rule" = "Host(`radarr.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.radarr.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.radarr.tls" = "true";
|
||||||
|
"traefik.http.routers.radarr.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.radarr.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.radarr.loadbalancer.server.port" = "7878";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Bazarr subtitle management
|
||||||
|
bazarr = {
|
||||||
|
image = "docker.io/linuxserver/bazarr:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/bazarr/config:/config"
|
||||||
|
"/mnt/storage/Media:/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.bazarr.rule" = "Host(`bazarr.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.bazarr.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.bazarr.tls" = "true";
|
||||||
|
"traefik.http.routers.bazarr.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.bazarr.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.bazarr.loadbalancer.server.port" = "6767";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# qBittorrent torrent client with host networking
|
||||||
|
qbittorrent = {
|
||||||
|
image = "docker.io/linuxserver/qbittorrent:4.6.7";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/qbit/config:/config"
|
||||||
|
"/mnt/storage/Media:/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.qbittorrent.rule" = "Host(`qbit.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.qbittorrent.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.qbittorrent.tls" = "true";
|
||||||
|
"traefik.http.routers.qbittorrent.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.qbittorrent.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.qbittorrent.loadbalancer.server.port" = "8080";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
TORRENTING_PORT = "41234";
|
||||||
|
WEBUI_PORT = "8080";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=host" # Use host networking as requested
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Paperless document management system
|
||||||
|
paperless = {
|
||||||
|
image = "ghcr.io/paperless-ngx/paperless-ngx:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/paperless/config:/usr/src/paperless/data"
|
||||||
|
"/mnt/storage/appbulk/Paperless/media:/usr/src/paperless/media"
|
||||||
|
"/mnt/storage/appbulk/Paperless/consume:/usr/src/paperless/consume"
|
||||||
|
"/mnt/storage/appbulk/Paperless/export:/usr/src/paperless/export"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.paperless.rule" = "Host(`paperless.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.paperless.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.paperless.tls" = "true";
|
||||||
|
"traefik.http.routers.paperless.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.paperless.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.paperless.loadbalancer.server.port" = "8000";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PAPERLESS_REDIS = "redis://paperless-redis:6379";
|
||||||
|
PAPERLESS_OCR_LANGUAGE = "eng+chi_sim";
|
||||||
|
PAPERLESS_OCR_LANGUAGES = "chi-sim";
|
||||||
|
PAPERLESS_FILENAME_FORMAT = "{{ created }}-{{ correspondent }}-{{ title }}";
|
||||||
|
PAPERLESS_TIME_ZONE = "Europe/Copenhagen";
|
||||||
|
PAPERLESS_URL = "https://paperless.${config.networking.hostName}.yanlincs.com";
|
||||||
|
PAPERLESS_CSRF_TRUSTED_ORIGINS = "https://paperless.${config.networking.hostName}.yanlincs.com";
|
||||||
|
PAPERLESS_ALLOWED_HOSTS = "paperless.${config.networking.hostName}.yanlincs.com";
|
||||||
|
PAPERLESS_CORS_ALLOWED_HOSTS = "https://paperless.${config.networking.hostName}.yanlincs.com";
|
||||||
|
PAPERLESS_SECRET_KEY = "e11fl1oa-*ytql8p)(06fbj4ukrlo+n7k&q5+$1md7i+mge=ee";
|
||||||
|
USERMAP_UID = commonUID;
|
||||||
|
USERMAP_GID = commonGID;
|
||||||
|
CA_TS_FALLBACK_DIR = "/usr/src/paperless/data";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
dependsOn = [ "paperless-redis" ];
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Redis cache for Paperless
|
||||||
|
paperless-redis = {
|
||||||
|
image = "docker.io/redis:7.2-alpine";
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# RSS reader (Miniflux)
|
||||||
|
rss = {
|
||||||
|
image = "docker.io/miniflux/miniflux:latest";
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.rss.rule" = "Host(`rss.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.rss.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.rss.tls" = "true";
|
||||||
|
"traefik.http.routers.rss.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.rss.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.rss.loadbalancer.server.port" = "8080";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
DATABASE_URL = "postgres://miniflux:miniflux@rss-db/miniflux?sslmode=disable";
|
||||||
|
ADMIN_USERNAME = "yanlin";
|
||||||
|
ADMIN_PASSWORD = "1Hayashi-2Hiko";
|
||||||
|
BASE_URL = "https://rss.${config.networking.hostName}.yanlincs.com";
|
||||||
|
CREATE_ADMIN = "1";
|
||||||
|
RUN_MIGRATIONS = "1";
|
||||||
|
HTTP_CLIENT_TIMEOUT = "50000";
|
||||||
|
POLLING_FREQUENCY = "60";
|
||||||
|
CLEANUP_FREQUENCY_HOURS = "24";
|
||||||
|
CLEANUP_ARCHIVE_READ_DAYS = "60";
|
||||||
|
CLEANUP_REMOVE_SESSIONS_DAYS = "30";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
dependsOn = [ "rss-db" ];
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# PostgreSQL database for RSS (Miniflux)
|
||||||
|
rss-db = {
|
||||||
|
image = "docker.io/postgres:17-alpine";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/rss/db:/var/lib/postgresql/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
POSTGRES_USER = "miniflux";
|
||||||
|
POSTGRES_PASSWORD = "miniflux";
|
||||||
|
POSTGRES_DB = "miniflux";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Linkding bookmark manager
|
||||||
|
linkding = {
|
||||||
|
image = "docker.io/sissbruecker/linkding:latest-plus";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/link:/etc/linkding/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.linkding.rule" = "Host(`link.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.linkding.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.linkding.tls" = "true";
|
||||||
|
"traefik.http.routers.linkding.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.linkding.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.linkding.loadbalancer.server.port" = "9090";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Nextcloud cloud storage and file sharing
|
||||||
|
cloud = {
|
||||||
|
image = "docker.io/linuxserver/nextcloud:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/cloud/config:/config"
|
||||||
|
"/mnt/storage/appbulk/cloud:/data"
|
||||||
|
];
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"traefik.enable" = "true";
|
||||||
|
"traefik.http.routers.cloud.rule" = "Host(`cloud.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
"traefik.http.routers.cloud.entrypoints" = "websecure";
|
||||||
|
"traefik.http.routers.cloud.tls" = "true";
|
||||||
|
"traefik.http.routers.cloud.tls.certresolver" = "cloudflare";
|
||||||
|
"traefik.http.routers.cloud.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
"traefik.http.services.cloud.loadbalancer.server.port" = "80";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = [
|
||||||
|
"5001:80"
|
||||||
|
];
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
dependsOn = [ "cloud-db" ];
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# MariaDB database for Nextcloud
|
||||||
|
cloud-db = {
|
||||||
|
image = "docker.io/linuxserver/mariadb:latest";
|
||||||
|
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/containers/cloud/db:/config"
|
||||||
|
];
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
PUID = commonUID;
|
||||||
|
PGID = commonGID;
|
||||||
|
TZ = systemTZ;
|
||||||
|
MYSQL_ROOT_PASSWORD = "nextcloud";
|
||||||
|
MYSQL_DATABASE = "nextcloud";
|
||||||
|
MYSQL_USER = "nextcloud";
|
||||||
|
MYSQL_PASSWORD = "nextcloud";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = [
|
||||||
|
"--network=podman"
|
||||||
|
];
|
||||||
|
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
30
hosts/nixos/hs/proxy.nix
Normal file
30
hosts/nixos/hs/proxy.nix
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# Traefik dynamic configuration for hs host
|
||||||
|
services.traefik.dynamicConfigOptions = {
|
||||||
|
http = {
|
||||||
|
routers = {
|
||||||
|
syncthing = {
|
||||||
|
rule = "Host(`syncthing.${config.networking.hostName}.yanlincs.com`)";
|
||||||
|
service = "syncthing";
|
||||||
|
tls = {
|
||||||
|
certResolver = "cloudflare";
|
||||||
|
domains = [{
|
||||||
|
main = "*.${config.networking.hostName}.yanlincs.com";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services = {
|
||||||
|
syncthing = {
|
||||||
|
loadBalancer = {
|
||||||
|
servers = [{
|
||||||
|
url = "http://localhost:8384";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./disk-config.nix
|
./disk-config.nix
|
||||||
|
./containers.nix # Host-specific container definitions
|
||||||
|
./proxy.nix # Host-specific Traefik dynamic configuration
|
||||||
../../../modules/tailscale.nix
|
../../../modules/tailscale.nix
|
||||||
../../../modules/podman.nix
|
../../../modules/podman.nix
|
||||||
../../../modules/traefik.nix
|
../../../modules/traefik.nix
|
||||||
|
|
|
||||||
7
hosts/nixos/vps/containers.nix
Normal file
7
hosts/nixos/vps/containers.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# Container definitions for vps host
|
||||||
|
virtualisation.oci-containers.containers = {
|
||||||
|
};
|
||||||
|
}
|
||||||
13
hosts/nixos/vps/proxy.nix
Normal file
13
hosts/nixos/vps/proxy.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# Traefik dynamic configuration for vps host
|
||||||
|
services.traefik.dynamicConfigOptions = {
|
||||||
|
http = {
|
||||||
|
routers = {
|
||||||
|
};
|
||||||
|
services = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,11 @@
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./disk-config.nix
|
./disk-config.nix
|
||||||
|
./containers.nix # Host-specific container definitions
|
||||||
|
./proxy.nix # Host-specific Traefik dynamic configuration
|
||||||
../../../modules/tailscale.nix
|
../../../modules/tailscale.nix
|
||||||
|
../../../modules/podman.nix
|
||||||
|
../../../modules/traefik.nix
|
||||||
../../../modules/borg.nix
|
../../../modules/borg.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -22,7 +26,7 @@
|
||||||
useDHCP = true; # VPS typically use DHCP
|
useDHCP = true; # VPS typically use DHCP
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowedTCPPorts = [ 22 ]; # Only SSH by default
|
allowedTCPPorts = [ 22 80 443 ]; # Only SSH by default
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,5 @@
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
let
|
|
||||||
# Import Immich configuration from declarative config file
|
|
||||||
immichConfig = import ../config/immich.nix;
|
|
||||||
|
|
||||||
# Convert Nix configuration to JSON string
|
|
||||||
immichConfigJson = builtins.toJSON immichConfig;
|
|
||||||
|
|
||||||
# Write config file to a location accessible by the container
|
|
||||||
immichConfigFile = pkgs.writeText "immich.json" immichConfigJson;
|
|
||||||
|
|
||||||
# Universal container configuration
|
|
||||||
commonUID = "1000";
|
|
||||||
commonGID = "100";
|
|
||||||
systemTZ = config.time.timeZone;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
# Container virtualization with Podman
|
# Container virtualization with Podman
|
||||||
virtualisation = {
|
virtualisation = {
|
||||||
|
|
@ -30,502 +15,8 @@ in
|
||||||
# Enable OCI container support
|
# Enable OCI container support
|
||||||
oci-containers = {
|
oci-containers = {
|
||||||
backend = "podman";
|
backend = "podman";
|
||||||
|
# Container definitions are now defined in host-specific containers.nix files
|
||||||
containers.homeassistant = {
|
# and will be merged with this base configuration
|
||||||
image = "ghcr.io/home-assistant/home-assistant:stable";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/home/config:/config"
|
|
||||||
"/etc/localtime:/etc/localtime:ro"
|
|
||||||
"/run/dbus:/run/dbus:ro"
|
|
||||||
# Mount declarative configuration files
|
|
||||||
"/home/yanlin/.config/nix/config/homeassistant/configuration.yaml:/config/configuration.yaml:ro"
|
|
||||||
"/home/yanlin/.config/nix/config/homeassistant/automations.yaml:/config/automations.yaml:ro"
|
|
||||||
"/home/yanlin/.config/nix/config/homeassistant/scenes.yaml:/config/scenes.yaml:ro"
|
|
||||||
"/home/yanlin/.config/nix/config/homeassistant/scripts.yaml:/config/scripts.yaml:ro"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.homeassistant.rule" = "Host(`home.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.homeassistant.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.homeassistant.tls" = "true";
|
|
||||||
"traefik.http.routers.homeassistant.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.homeassistant.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.homeassistant.loadbalancer.server.port" = "8123";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
TZ = systemTZ;
|
|
||||||
# Configure Home Assistant to trust reverse proxy
|
|
||||||
HASS_HTTP_TRUSTED_PROXY_1 = "127.0.0.1";
|
|
||||||
HASS_HTTP_TRUSTED_PROXY_2 = "::1";
|
|
||||||
HASS_HTTP_USE_X_FORWARDED_FOR = "true";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--privileged" # Required for USB device access
|
|
||||||
"--network=host" # Use host networking
|
|
||||||
"--device=/dev/ttyUSB0:/dev/ttyUSB0" # Sky Connect Zigbee dongle
|
|
||||||
"--device=/dev/dri:/dev/dri" # Hardware acceleration
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Immich photo and video backup system
|
|
||||||
containers.immich = {
|
|
||||||
image = "ghcr.io/imagegenius/immich:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/immich/config:/config"
|
|
||||||
"/mnt/storage/appbulk/immich:/photos"
|
|
||||||
"/mnt/storage/Media/DCIM:/libraries"
|
|
||||||
# Mount the declarative config file
|
|
||||||
"${immichConfigFile}:/config/immich.json:ro"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.immich.rule" = "Host(`photo.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.immich.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.immich.tls" = "true";
|
|
||||||
"traefik.http.routers.immich.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.immich.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.immich.loadbalancer.server.port" = "8080";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
# Point to the mounted config file
|
|
||||||
IMMICH_CONFIG_FILE = "/config/immich.json";
|
|
||||||
# Database connection (keep as env vars for security)
|
|
||||||
DB_HOSTNAME = "immich-db";
|
|
||||||
DB_USERNAME = "postgres";
|
|
||||||
DB_PASSWORD = "postgres";
|
|
||||||
DB_DATABASE_NAME = "postgres";
|
|
||||||
DB_PORT = "5432";
|
|
||||||
# Redis connection
|
|
||||||
REDIS_HOSTNAME = "immich-redis";
|
|
||||||
REDIS_PORT = "6379";
|
|
||||||
# Machine Learning server (internal)
|
|
||||||
MACHINE_LEARNING_HOST = "0.0.0.0";
|
|
||||||
MACHINE_LEARNING_PORT = "3003";
|
|
||||||
MACHINE_LEARNING_WORKERS = "1";
|
|
||||||
MACHINE_LEARNING_WORKER_TIMEOUT = "120";
|
|
||||||
};
|
|
||||||
|
|
||||||
ports = [
|
|
||||||
"5000:8080"
|
|
||||||
];
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
"--device=/dev/dri:/dev/dri" # Hardware acceleration
|
|
||||||
];
|
|
||||||
|
|
||||||
dependsOn = [ "immich-db" "immich-redis" ];
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# PostgreSQL database for Immich with vector extension
|
|
||||||
containers.immich-db = {
|
|
||||||
image = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/immich/db:/var/lib/postgresql/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
POSTGRES_PASSWORD = "postgres";
|
|
||||||
POSTGRES_USER = "postgres";
|
|
||||||
POSTGRES_DB = "postgres";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Redis cache for Immich
|
|
||||||
containers.immich-redis = {
|
|
||||||
image = "docker.io/redis:7.2-alpine";
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Plex Media Server
|
|
||||||
containers.plex = {
|
|
||||||
image = "docker.io/linuxserver/plex:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/plex/config:/config"
|
|
||||||
"/mnt/storage/appbulk/plex-transcode:/transcode"
|
|
||||||
"/mnt/storage/Media:/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.plex.rule" = "Host(`plex.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.plex.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.plex.tls" = "true";
|
|
||||||
"traefik.http.routers.plex.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.plex.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.plex.loadbalancer.server.port" = "32400";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
VERSION = "docker";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
"--device=/dev/dri:/dev/dri" # Hardware acceleration
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Sonarr TV show management
|
|
||||||
containers.sonarr = {
|
|
||||||
image = "docker.io/linuxserver/sonarr:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/sonarr/config:/config"
|
|
||||||
"/mnt/storage/Media:/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.sonarr.rule" = "Host(`sonarr.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.sonarr.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.sonarr.tls" = "true";
|
|
||||||
"traefik.http.routers.sonarr.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.sonarr.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.sonarr.loadbalancer.server.port" = "8989";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Radarr movie management
|
|
||||||
containers.radarr = {
|
|
||||||
image = "docker.io/linuxserver/radarr:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/radarr/config:/config"
|
|
||||||
"/mnt/storage/Media:/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.radarr.rule" = "Host(`radarr.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.radarr.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.radarr.tls" = "true";
|
|
||||||
"traefik.http.routers.radarr.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.radarr.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.radarr.loadbalancer.server.port" = "7878";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Bazarr subtitle management
|
|
||||||
containers.bazarr = {
|
|
||||||
image = "docker.io/linuxserver/bazarr:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/bazarr/config:/config"
|
|
||||||
"/mnt/storage/Media:/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.bazarr.rule" = "Host(`bazarr.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.bazarr.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.bazarr.tls" = "true";
|
|
||||||
"traefik.http.routers.bazarr.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.bazarr.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.bazarr.loadbalancer.server.port" = "6767";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# qBittorrent torrent client with host networking
|
|
||||||
containers.qbittorrent = {
|
|
||||||
image = "docker.io/linuxserver/qbittorrent:4.6.7";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/qbit/config:/config"
|
|
||||||
"/mnt/storage/Media:/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.qbittorrent.rule" = "Host(`qbit.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.qbittorrent.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.qbittorrent.tls" = "true";
|
|
||||||
"traefik.http.routers.qbittorrent.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.qbittorrent.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.qbittorrent.loadbalancer.server.port" = "8080";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
TORRENTING_PORT = "41234";
|
|
||||||
WEBUI_PORT = "8080";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=host" # Use host networking as requested
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Paperless document management system
|
|
||||||
containers.paperless = {
|
|
||||||
image = "ghcr.io/paperless-ngx/paperless-ngx:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/paperless/config:/usr/src/paperless/data"
|
|
||||||
"/mnt/storage/appbulk/Paperless/media:/usr/src/paperless/media"
|
|
||||||
"/mnt/storage/appbulk/Paperless/consume:/usr/src/paperless/consume"
|
|
||||||
"/mnt/storage/appbulk/Paperless/export:/usr/src/paperless/export"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.paperless.rule" = "Host(`paperless.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.paperless.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.paperless.tls" = "true";
|
|
||||||
"traefik.http.routers.paperless.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.paperless.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.paperless.loadbalancer.server.port" = "8000";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PAPERLESS_REDIS = "redis://paperless-redis:6379";
|
|
||||||
PAPERLESS_OCR_LANGUAGE = "eng+chi_sim";
|
|
||||||
PAPERLESS_OCR_LANGUAGES = "chi-sim";
|
|
||||||
PAPERLESS_FILENAME_FORMAT = "{{ created }}-{{ correspondent }}-{{ title }}";
|
|
||||||
PAPERLESS_TIME_ZONE = "Europe/Copenhagen";
|
|
||||||
PAPERLESS_URL = "https://paperless.${config.networking.hostName}.yanlincs.com";
|
|
||||||
PAPERLESS_CSRF_TRUSTED_ORIGINS = "https://paperless.${config.networking.hostName}.yanlincs.com";
|
|
||||||
PAPERLESS_ALLOWED_HOSTS = "paperless.${config.networking.hostName}.yanlincs.com";
|
|
||||||
PAPERLESS_CORS_ALLOWED_HOSTS = "https://paperless.${config.networking.hostName}.yanlincs.com";
|
|
||||||
PAPERLESS_SECRET_KEY = "e11fl1oa-*ytql8p)(06fbj4ukrlo+n7k&q5+$1md7i+mge=ee";
|
|
||||||
USERMAP_UID = commonUID;
|
|
||||||
USERMAP_GID = commonGID;
|
|
||||||
CA_TS_FALLBACK_DIR = "/usr/src/paperless/data";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
dependsOn = [ "paperless-redis" ];
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Redis cache for Paperless
|
|
||||||
containers.paperless-redis = {
|
|
||||||
image = "docker.io/redis:7.2-alpine";
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# RSS reader (Miniflux)
|
|
||||||
containers.rss = {
|
|
||||||
image = "docker.io/miniflux/miniflux:latest";
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.rss.rule" = "Host(`rss.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.rss.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.rss.tls" = "true";
|
|
||||||
"traefik.http.routers.rss.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.rss.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.rss.loadbalancer.server.port" = "8080";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
DATABASE_URL = "postgres://miniflux:miniflux@rss-db/miniflux?sslmode=disable";
|
|
||||||
ADMIN_USERNAME = "yanlin";
|
|
||||||
ADMIN_PASSWORD = "1Hayashi-2Hiko";
|
|
||||||
BASE_URL = "https://rss.${config.networking.hostName}.yanlincs.com";
|
|
||||||
CREATE_ADMIN = "1";
|
|
||||||
RUN_MIGRATIONS = "1";
|
|
||||||
HTTP_CLIENT_TIMEOUT = "50000";
|
|
||||||
POLLING_FREQUENCY = "60";
|
|
||||||
CLEANUP_FREQUENCY_HOURS = "24";
|
|
||||||
CLEANUP_ARCHIVE_READ_DAYS = "60";
|
|
||||||
CLEANUP_REMOVE_SESSIONS_DAYS = "30";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
dependsOn = [ "rss-db" ];
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# PostgreSQL database for RSS (Miniflux)
|
|
||||||
containers.rss-db = {
|
|
||||||
image = "docker.io/postgres:17-alpine";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/rss/db:/var/lib/postgresql/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
POSTGRES_USER = "miniflux";
|
|
||||||
POSTGRES_PASSWORD = "miniflux";
|
|
||||||
POSTGRES_DB = "miniflux";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Linkding bookmark manager
|
|
||||||
containers.linkding = {
|
|
||||||
image = "docker.io/sissbruecker/linkding:latest-plus";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/link:/etc/linkding/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.linkding.rule" = "Host(`link.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.linkding.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.linkding.tls" = "true";
|
|
||||||
"traefik.http.routers.linkding.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.linkding.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.linkding.loadbalancer.server.port" = "9090";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Nextcloud cloud storage and file sharing
|
|
||||||
containers.cloud = {
|
|
||||||
image = "docker.io/linuxserver/nextcloud:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/cloud/config:/config"
|
|
||||||
"/mnt/storage/appbulk/cloud:/data"
|
|
||||||
];
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
"traefik.enable" = "true";
|
|
||||||
"traefik.http.routers.cloud.rule" = "Host(`cloud.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
"traefik.http.routers.cloud.entrypoints" = "websecure";
|
|
||||||
"traefik.http.routers.cloud.tls" = "true";
|
|
||||||
"traefik.http.routers.cloud.tls.certresolver" = "cloudflare";
|
|
||||||
"traefik.http.routers.cloud.tls.domains[0].main" = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
"traefik.http.services.cloud.loadbalancer.server.port" = "80";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
};
|
|
||||||
|
|
||||||
ports = [
|
|
||||||
"5001:80"
|
|
||||||
];
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
dependsOn = [ "cloud-db" ];
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# MariaDB database for Nextcloud
|
|
||||||
containers.cloud-db = {
|
|
||||||
image = "docker.io/linuxserver/mariadb:latest";
|
|
||||||
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/containers/cloud/db:/config"
|
|
||||||
];
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
PUID = commonUID;
|
|
||||||
PGID = commonGID;
|
|
||||||
TZ = systemTZ;
|
|
||||||
MYSQL_ROOT_PASSWORD = "nextcloud";
|
|
||||||
MYSQL_DATABASE = "nextcloud";
|
|
||||||
MYSQL_USER = "nextcloud";
|
|
||||||
MYSQL_PASSWORD = "nextcloud";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--network=podman"
|
|
||||||
];
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -6,10 +6,6 @@
|
||||||
enable = true;
|
enable = true;
|
||||||
# Enable MagicDNS for better name resolution on NixOS server
|
# Enable MagicDNS for better name resolution on NixOS server
|
||||||
useRoutingFeatures = "server";
|
useRoutingFeatures = "server";
|
||||||
extraUpFlags = [
|
|
||||||
"--advertise-routes=10.1.1.0/24"
|
|
||||||
"--advertise-exit-node"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Allow Tailscale through the firewall if enabled
|
# Allow Tailscale through the firewall if enabled
|
||||||
|
|
|
||||||
|
|
@ -63,32 +63,8 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Dynamic configuration for services not running in containers
|
# Dynamic configuration is now defined in host-specific proxy.nix files
|
||||||
dynamicConfigOptions = {
|
# and will be merged with this base configuration
|
||||||
http = {
|
|
||||||
routers = {
|
|
||||||
syncthing = {
|
|
||||||
rule = "Host(`syncthing.${config.networking.hostName}.yanlincs.com`)";
|
|
||||||
service = "syncthing";
|
|
||||||
tls = {
|
|
||||||
certResolver = "cloudflare";
|
|
||||||
domains = [{
|
|
||||||
main = "*.${config.networking.hostName}.yanlincs.com";
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
services = {
|
|
||||||
syncthing = {
|
|
||||||
loadBalancer = {
|
|
||||||
servers = [{
|
|
||||||
url = "http://localhost:8384";
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Environment variables for Cloudflare
|
# Environment variables for Cloudflare
|
||||||
environmentFiles = [ "/run/secrets/traefik-env" ];
|
environmentFiles = [ "/run/secrets/traefik-env" ];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue