+zammad-hr
This commit is contained in:
parent
e57419dd2d
commit
7bbcd5ae4e
@ -123,9 +123,15 @@ in {
|
|||||||
show_edit_predictions = true;
|
show_edit_predictions = true;
|
||||||
ssh_connections = [
|
ssh_connections = [
|
||||||
{
|
{
|
||||||
args = ["-i" "~/.ssh/m3tam3re"];
|
args = ["-i" "~/.ssh/sascha.koenig"];
|
||||||
host = "152.53.85.162";
|
host = "152.53.186.119";
|
||||||
nickname = "m3-atlas";
|
port = 2022;
|
||||||
|
nickname = "AZ-CLD-1";
|
||||||
|
"projects" = [
|
||||||
|
{
|
||||||
|
paths = ["/home/sascha.koenig/AZ-NIX"];
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
telemetry = {
|
telemetry = {
|
||||||
|
|||||||
@ -54,6 +54,12 @@
|
|||||||
file = ../../secrets/zammad-secret.age;
|
file = ../../secrets/zammad-secret.age;
|
||||||
owner = "zammad";
|
owner = "zammad";
|
||||||
};
|
};
|
||||||
|
zammad-hr-env-prod = {
|
||||||
|
file = ../../secrets/zammad-hr-env-prod.age;
|
||||||
|
};
|
||||||
|
zammad-hr-env = {
|
||||||
|
file = ../../secrets/zammad-hr-env.age;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
./litellm.nix
|
./litellm.nix
|
||||||
./librechat-dev.nix
|
./librechat-dev.nix
|
||||||
./portainer.nix
|
./portainer.nix
|
||||||
|
./zammad-hr.nix
|
||||||
];
|
];
|
||||||
system.activationScripts.createPodmanNetworkWeb = lib.mkAfter ''
|
system.activationScripts.createPodmanNetworkWeb = lib.mkAfter ''
|
||||||
if ! /run/current-system/sw/bin/podman network exists web; then
|
if ! /run/current-system/sw/bin/podman network exists web; then
|
||||||
|
|||||||
238
hosts/AZ-CLD-1/services/containers/zammad-hr.nix
Normal file
238
hosts/AZ-CLD-1/services/containers/zammad-hr.nix
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
# Instance identifier - macht es einfach, später eine zweite Instanz zu erstellen
|
||||||
|
instanceName = "hr";
|
||||||
|
serviceName = "zammad-${instanceName}";
|
||||||
|
|
||||||
|
portUtils = import ../../../../lib/port-utils.nix {inherit lib;};
|
||||||
|
servicePort = portUtils.getPort serviceName "AZ-CLD-1";
|
||||||
|
elasticsearchPort = portUtils.getPort "${serviceName}-elasticsearch" "AZ-CLD-1";
|
||||||
|
|
||||||
|
envFileProd = config.age.secrets."${serviceName}-env-prod".path;
|
||||||
|
envFileCommon = config.age.secrets."${serviceName}-env".path;
|
||||||
|
|
||||||
|
# Zammad version
|
||||||
|
zammadVersion = "6.5.2-22";
|
||||||
|
zammadImage = "ghcr.io/zammad/zammad:${zammadVersion}";
|
||||||
|
|
||||||
|
# IP-Basis für diese Instanz (HR: .30-.38, später IT: .40-.48)
|
||||||
|
ipBase = "10.89.0";
|
||||||
|
ipOffset = 30; # HR startet bei .30, IT würde bei .40 starten
|
||||||
|
|
||||||
|
# Shared environment variables
|
||||||
|
sharedEnvironment = {
|
||||||
|
MEMCACHE_SERVERS = "${serviceName}-memcached:11211";
|
||||||
|
POSTGRESQL_DB = "zammad_${instanceName}";
|
||||||
|
POSTGRESQL_HOST = "10.89.0.1"; # Host PostgreSQL
|
||||||
|
POSTGRESQL_USER = "zammad_${instanceName}";
|
||||||
|
POSTGRESQL_PORT = "5432";
|
||||||
|
POSTGRESQL_OPTIONS = "?pool=50";
|
||||||
|
REDIS_URL = "redis://${serviceName}-redis:6379";
|
||||||
|
TZ = "Europe/Berlin";
|
||||||
|
BACKUP_DIR = "/var/tmp/zammad";
|
||||||
|
BACKUP_TIME = "03:00";
|
||||||
|
HOLD_DAYS = "10";
|
||||||
|
ELASTICSEARCH_ENABLED = "true";
|
||||||
|
ELASTICSEARCH_HOST = "${serviceName}-elasticsearch";
|
||||||
|
ELASTICSEARCH_PORT = "9200";
|
||||||
|
ELASTICSEARCH_NAMESPACE = "zammad_${instanceName}";
|
||||||
|
NGINX_PORT = "8080";
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
virtualisation.oci-containers = {
|
||||||
|
containers."${serviceName}-elasticsearch" = {
|
||||||
|
image = "elasticsearch:8.19.6";
|
||||||
|
autoStart = true;
|
||||||
|
volumes = ["${serviceName}_elasticsearch:/usr/share/elasticsearch/data"];
|
||||||
|
environment = {
|
||||||
|
"discovery.type" = "single-node";
|
||||||
|
"xpack.security.enabled" = "false";
|
||||||
|
ES_JAVA_OPTS = "-Xms1g -Xmx1g";
|
||||||
|
};
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString ipOffset}"
|
||||||
|
"--network=web"
|
||||||
|
];
|
||||||
|
ports = ["127.0.0.1:${toString elasticsearchPort}:9200"];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-memcached" = {
|
||||||
|
image = "memcached:1.6.39-alpine";
|
||||||
|
autoStart = true;
|
||||||
|
cmd = ["memcached" "-m" "256M"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 1)}"
|
||||||
|
"--network=web"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-redis" = {
|
||||||
|
image = "redis:7.4.6-alpine";
|
||||||
|
autoStart = true;
|
||||||
|
volumes = ["${serviceName}_redis:/data"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 2)}"
|
||||||
|
"--network=web"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-init" = {
|
||||||
|
image = zammadImage;
|
||||||
|
autoStart = false;
|
||||||
|
cmd = ["zammad-init"];
|
||||||
|
environment = sharedEnvironment;
|
||||||
|
environmentFiles = [envFileCommon envFileProd];
|
||||||
|
volumes = ["${serviceName}_storage:/opt/zammad/storage"];
|
||||||
|
dependsOn = ["${serviceName}-memcached" "${serviceName}-redis"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 3)}"
|
||||||
|
"--network=web"
|
||||||
|
"--add-host=postgres:10.89.0.1"
|
||||||
|
"--user=0:0"
|
||||||
|
"--restart=on-failure"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-railsserver" = {
|
||||||
|
image = zammadImage;
|
||||||
|
autoStart = true;
|
||||||
|
cmd = ["zammad-railsserver"];
|
||||||
|
environment = sharedEnvironment;
|
||||||
|
environmentFiles = [envFileCommon envFileProd];
|
||||||
|
volumes = ["${serviceName}_storage:/opt/zammad/storage"];
|
||||||
|
dependsOn = ["${serviceName}-memcached" "${serviceName}-redis" "${serviceName}-elasticsearch"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 4)}"
|
||||||
|
"--network=web"
|
||||||
|
"--add-host=postgres:10.89.0.1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-scheduler" = {
|
||||||
|
image = zammadImage;
|
||||||
|
autoStart = true;
|
||||||
|
cmd = ["zammad-scheduler"];
|
||||||
|
environment = sharedEnvironment;
|
||||||
|
environmentFiles = [envFileCommon envFileProd];
|
||||||
|
volumes = ["${serviceName}_storage:/opt/zammad/storage"];
|
||||||
|
dependsOn = ["${serviceName}-memcached" "${serviceName}-redis"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 5)}"
|
||||||
|
"--network=web"
|
||||||
|
"--add-host=postgres:10.89.0.1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-websocket" = {
|
||||||
|
image = zammadImage;
|
||||||
|
autoStart = true;
|
||||||
|
cmd = ["zammad-websocket"];
|
||||||
|
environment = sharedEnvironment;
|
||||||
|
environmentFiles = [envFileCommon envFileProd];
|
||||||
|
volumes = ["${serviceName}_storage:/opt/zammad/storage"];
|
||||||
|
dependsOn = ["${serviceName}-memcached" "${serviceName}-redis"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 6)}"
|
||||||
|
"--network=web"
|
||||||
|
"--add-host=postgres:10.89.0.1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-nginx" = {
|
||||||
|
image = zammadImage;
|
||||||
|
autoStart = true;
|
||||||
|
cmd = ["zammad-nginx"];
|
||||||
|
environment = sharedEnvironment;
|
||||||
|
environmentFiles = [envFileCommon envFileProd];
|
||||||
|
volumes = ["${serviceName}_storage:/opt/zammad/storage"];
|
||||||
|
dependsOn = ["${serviceName}-railsserver"];
|
||||||
|
ports = ["127.0.0.1:${toString servicePort}:8080"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 7)}"
|
||||||
|
"--network=web"
|
||||||
|
"--add-host=postgres:10.89.0.1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
containers."${serviceName}-backup" = {
|
||||||
|
image = zammadImage;
|
||||||
|
autoStart = true;
|
||||||
|
cmd = ["zammad-backup"];
|
||||||
|
environment = sharedEnvironment;
|
||||||
|
environmentFiles = [envFileCommon envFileProd];
|
||||||
|
volumes = [
|
||||||
|
"${serviceName}_backup:/var/tmp/zammad"
|
||||||
|
"${serviceName}_storage:/opt/zammad/storage:ro"
|
||||||
|
"/var/backup/${serviceName}:/var/tmp/zammad:rw"
|
||||||
|
];
|
||||||
|
dependsOn = ["${serviceName}-memcached" "${serviceName}-redis"];
|
||||||
|
extraOptions = [
|
||||||
|
"--ip=${ipBase}.${toString (ipOffset + 8)}"
|
||||||
|
"--network=web"
|
||||||
|
"--add-host=postgres:10.89.0.1"
|
||||||
|
"--user=0:0"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Backup retention service
|
||||||
|
systemd.services."${serviceName}-backup-cleanup" = {
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
User = "root";
|
||||||
|
Group = "root";
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BACKUP_DIR="/var/backup/${serviceName}"
|
||||||
|
HOLD_DAYS=10
|
||||||
|
|
||||||
|
echo "Starting ${serviceName} backup cleanup at $(date)"
|
||||||
|
|
||||||
|
# Ensure backup directory exists
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
chown root:root "$BACKUP_DIR"
|
||||||
|
chmod 750 "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Remove backups older than HOLD_DAYS
|
||||||
|
${pkgs.findutils}/bin/find "$BACKUP_DIR" -type f -name "*.gz" -mtime +$HOLD_DAYS -delete
|
||||||
|
|
||||||
|
echo "Current backups:"
|
||||||
|
ls -lah "$BACKUP_DIR" || echo "No backups found"
|
||||||
|
|
||||||
|
echo "${serviceName} backup cleanup completed at $(date)"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.timers."${serviceName}-backup-cleanup" = {
|
||||||
|
wantedBy = ["timers.target"];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "*-*-* 04:00:00";
|
||||||
|
RandomizedDelaySec = "30m";
|
||||||
|
Persistent = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Traefik configuration
|
||||||
|
services.traefik.dynamicConfigOptions.http = {
|
||||||
|
services.${serviceName}.loadBalancer.servers = [
|
||||||
|
{
|
||||||
|
url = "http://localhost:${toString servicePort}/";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
routers.${serviceName} = {
|
||||||
|
rule = "Host(`hr-ticket.az-gruppe.com`)"; # HR-spezifische Domain
|
||||||
|
tls = {
|
||||||
|
certResolver = "ionos";
|
||||||
|
};
|
||||||
|
service = serviceName;
|
||||||
|
entrypoints = "websecure";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -72,10 +72,10 @@
|
|||||||
ALTER DATABASE vaultwarden OWNER to vaultwarden;
|
ALTER DATABASE vaultwarden OWNER to vaultwarden;
|
||||||
ALTER DATABASE vaultwarden CONNECTION LIMIT 20;
|
ALTER DATABASE vaultwarden CONNECTION LIMIT 20;
|
||||||
|
|
||||||
CREATE USER zammad WITH ENCRYPTED PASSWORD 'zammad';
|
CREATE USER zammad-hr WITH ENCRYPTED PASSWORD 'zammad-hr';
|
||||||
CREATE DATABASE zammad;
|
CREATE DATABASE zammad-hr;
|
||||||
ALTER DATABASE zammad OWNER to zammad;
|
ALTER DATABASE zammad-hr OWNER to zammad-hr;
|
||||||
ALTER DATABASE zammad CONNECTION LIMIT 50;
|
ALTER DATABASE zammad-hr CONNECTION LIMIT 50;
|
||||||
'';
|
'';
|
||||||
authentication = pkgs.lib.mkOverride 10 ''
|
authentication = pkgs.lib.mkOverride 10 ''
|
||||||
# Local connections (Unix socket)
|
# Local connections (Unix socket)
|
||||||
@ -114,6 +114,7 @@
|
|||||||
host kestra kestra 10.89.0.0/24 scram-sha-256
|
host kestra kestra 10.89.0.0/24 scram-sha-256
|
||||||
host librechat_rag librechat_rag 10.89.0.0/24 scram-sha-256
|
host librechat_rag librechat_rag 10.89.0.0/24 scram-sha-256
|
||||||
host librechat_rag_dev librechat_rag_dev 10.89.1.0/24 scram-sha-256
|
host librechat_rag_dev librechat_rag_dev 10.89.1.0/24 scram-sha-256
|
||||||
|
host zammad_hr zammad_hr 10.89.0.0/24 scram-sha-256
|
||||||
host litellm litellm 10.89.0.0/24 scram-sha-256
|
host litellm litellm 10.89.0.0/24 scram-sha-256
|
||||||
|
|
||||||
# Deny all other connections
|
# Deny all other connections
|
||||||
@ -125,7 +126,7 @@
|
|||||||
services.postgresqlBackup = {
|
services.postgresqlBackup = {
|
||||||
enable = true;
|
enable = true;
|
||||||
startAt = "03:10:00";
|
startAt = "03:10:00";
|
||||||
databases = ["baserow" "kestra" "librechat_rag" "metabase" "n8n" "outline" "vaultwarden" "zammad"];
|
databases = ["baserow" "kestra" "librechat_rag" "litellm" "metabase" "n8n" "outline" "vaultwarden" "zammad" "zammad_hr"];
|
||||||
};
|
};
|
||||||
services.pgadmin = {
|
services.pgadmin = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
metabase = 3013;
|
metabase = 3013;
|
||||||
ntfy-sh = 3033;
|
ntfy-sh = 3033;
|
||||||
it-tools = 3035;
|
it-tools = 3035;
|
||||||
|
zammad-hr = 3036;
|
||||||
|
zammad-hr-elasticsearch = 3037;
|
||||||
|
|
||||||
# Docker services (3100-3199 range)
|
# Docker services (3100-3199 range)
|
||||||
librechat = 3040;
|
librechat = 3040;
|
||||||
|
|||||||
@ -29,4 +29,6 @@ in {
|
|||||||
"secrets/vaultwarden-db.age".publicKeys = systems ++ users;
|
"secrets/vaultwarden-db.age".publicKeys = systems ++ users;
|
||||||
"secrets/zammad-pw.age".publicKeys = systems ++ users;
|
"secrets/zammad-pw.age".publicKeys = systems ++ users;
|
||||||
"secrets/zammad-secret.age".publicKeys = systems ++ users;
|
"secrets/zammad-secret.age".publicKeys = systems ++ users;
|
||||||
|
"secrets/zammad-hr-env.age".publicKeys = systems ++ users;
|
||||||
|
"secrets/zammad-hr-env-prod.age".publicKeys = systems ++ users;
|
||||||
}
|
}
|
||||||
|
|||||||
12
secrets/zammad-hr-env-prod.age
Normal file
12
secrets/zammad-hr-env-prod.age
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpoVnNlZyBQMzFq
|
||||||
|
VXRGU2hHVjFuazdvdE5GM3puenBlV0pNekh1WFNLaHUzOHNNZWswCll1VEtsbVlS
|
||||||
|
Uys3SVNmUS9pS0lGWE5GdUhyNDhsZldkYUlxd2w1ODN2RFEKLT4gc3NoLWVkMjU1
|
||||||
|
MTkgQ1NNeWhnIHRsSTR6alh3ZFZNYjFCdXBIenVuaXdPd1FDKzlXa3NnWktvYmxv
|
||||||
|
eG1Tak0Kd0lESnJKZVNYUGp0SEJDNzZYQXUyVlNGaDh5LzA1amNrZFdtQmdQalg3
|
||||||
|
awotPiA7R0ciZG8tZ3JlYXNlCjlEVlFicnByZHRPNGs1SG92ZjJKV295Y3VyMjM0
|
||||||
|
cDlrcDQrMnVrMk54bjlrTG1PSUZrL2NrSlZvYWtVVHlwbHIKTWZYdjFRCi0tLSBk
|
||||||
|
WnMvaFZsTmlSOWRRa0prZXJQVkxta240Sm1TWkIrQ21LZytEUHJOckRRCk7tRMUc
|
||||||
|
s3agudDWyiHVrLZKwDFR7peGyHCfXNV19kpDThVKxKe3DzWGWWDYwggblHJbUnAj
|
||||||
|
OpIA/tq0s2nNc2F5Db2Hm7qen7YnOhF7WDoRPTXdG6VRERBqrZ/3
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
12
secrets/zammad-hr-env.age
Normal file
12
secrets/zammad-hr-env.age
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpoVnNlZyBsc0xG
|
||||||
|
VzRzRGMxZ3h4MU1jZkZ4MEQzbUhaS0JYSzZ5eTZ5YXhWZEtTbWxFCnBrT2RKaEdN
|
||||||
|
U1BRRnZBWVYyWVpxTVhVM0d4VzhtbEEzNnoza0xpSEtQbXcKLT4gc3NoLWVkMjU1
|
||||||
|
MTkgQ1NNeWhnIGNySDFJcjN4SEFReG5kUVBTdXVjWEpLRG8rSWVlSkI3WXovWE5q
|
||||||
|
N3dZQVEKaWdJVVJuWUM1MEZGaTQrV3c2YVRSTmRIYk4wdkVnRStuWG5UVGxjQ0FP
|
||||||
|
TQotPiAtV3l1P0sjLWdyZWFzZQpGb1gzY0pYNHBGRjUvK2JhWlBDdHZtSnROaU5X
|
||||||
|
aVc2L3hCSDJrUnJEdHNaUkFZT1cxK25IKzJza0VTb3hsTEFBCnkxSUJ2TFA3Sllz
|
||||||
|
UGVQY285djc2eXhtU2wrbldtTnkyRGZONgotLS0gV0Y5Qk53TXNhYUozTVZlQjRh
|
||||||
|
RHRNOWs2RS9jNzA0cW53b09ucGZQSURyYwomvbCCgvqCeAaza/IO2/ih4OOOWJHO
|
||||||
|
m579mV6FSO0Ak2+AdYVWC6ddOqQEuqPwTmAkebfrSJ3IajZtczXtj8k=
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
Loading…
x
Reference in New Issue
Block a user