mirror of
https://github.com/harryssecret/homelab-nix.git
synced 2025-02-23 06:43:57 +01:00
splitted configs in even more files
This commit is contained in:
parent
4c19ad042f
commit
fb2934c4c7
|
@ -1,4 +1,9 @@
|
|||
{ pkgs }:
|
||||
{ pkgs, lib }:
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.arrSuite;
|
||||
in
|
||||
{
|
||||
services.sonarr = {
|
||||
enable = true;
|
||||
|
@ -26,11 +31,29 @@
|
|||
enable = true;
|
||||
};
|
||||
|
||||
systemd.services.sonarrAnime = {
|
||||
services.bazarr = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
#TODO: create duplicated instances of Sonarr.
|
||||
systemd.services."sonarrAnime" = {
|
||||
enable = true;
|
||||
description = "Duplicated Sonarr instance, for animes";
|
||||
after = [
|
||||
"syslog.target"
|
||||
"network.target"
|
||||
];
|
||||
|
||||
path = [ pkgs.sonarr ];
|
||||
serviceConfig = {
|
||||
ExecStart = "Sonarr -nobrowser -data=/var/lib/sonarrAnime";
|
||||
Type = "simple";
|
||||
User = "sonarr";
|
||||
ExecStart = "${pkgs.sonarr}/bin/Sonarr -nobrowser -data=/var/lib/sonarrAnime";
|
||||
TimeoutStopSec = "20";
|
||||
KillMode = "process";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ let
|
|||
sha256 = "15b9a2csd2m3vwhj3xc24nrqnj1hal60jrd69splln0ynbnd9ki4";
|
||||
};
|
||||
authentik-nix = import authentik-nix-src;
|
||||
cfg = config.authentik;
|
||||
in
|
||||
{
|
||||
|
||||
imports = [ authentik-nix.nixosModules.default ];
|
||||
|
||||
sops.secrets."authentik" = {
|
||||
|
@ -16,16 +16,25 @@ in
|
|||
format = "dotenv";
|
||||
};
|
||||
|
||||
/*
|
||||
sops.secrets.mail-server = {
|
||||
sopsFile = ./secrets/mail.json;
|
||||
format = "json";
|
||||
};
|
||||
*/
|
||||
|
||||
services.authentik = {
|
||||
enable = true;
|
||||
environmentFile = config.sops.secrets."authentik".path;
|
||||
settings = {
|
||||
email = {
|
||||
|
||||
};
|
||||
/*
|
||||
email = {
|
||||
host = config.sops.secrets.mail-server."host";
|
||||
username = config.sops.secrets.mail-server."username";
|
||||
};
|
||||
*/
|
||||
|
||||
disable_startup_analytics = true;
|
||||
|
||||
avatars = "initials";
|
||||
};
|
||||
};
|
||||
|
|
11
features/calibre-web.nix
Normal file
11
features/calibre-web.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{ }:
|
||||
|
||||
{
|
||||
services.calibre-web = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
options = {
|
||||
enableBookUploading = true;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,34 +1,48 @@
|
|||
{ ... }:
|
||||
{ lib, ... }:
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.containers;
|
||||
in
|
||||
{
|
||||
# docker containers, for apps that aren't avaiable on Nix. (yet)
|
||||
virtualisation.oci-containers = {
|
||||
backend = "docker";
|
||||
containers = {
|
||||
flaresolverr = {
|
||||
ports = [ "8191:8191" ];
|
||||
image = "ghcr.io/flaresolverr/flaresolverr:latest";
|
||||
environment = {
|
||||
"LOG_LEVEL" = "info";
|
||||
options.containers = {
|
||||
minecraft.path = mkOption {
|
||||
type = types.str;
|
||||
default = "/srv/Minecraft";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
|
||||
# docker containers, for apps that aren't avaiable on Nix. (yet)
|
||||
virtualisation.oci-containers = {
|
||||
backend = "docker";
|
||||
containers = {
|
||||
flaresolverr = {
|
||||
ports = [ "8191:8191" ];
|
||||
image = "ghcr.io/flaresolverr/flaresolverr:latest";
|
||||
environment = {
|
||||
"LOG_LEVEL" = "info";
|
||||
};
|
||||
};
|
||||
};
|
||||
crafty-controller = {
|
||||
image = "registry.gitlab.com/crafty-controller/crafty-4:latest";
|
||||
ports = [
|
||||
"8443:8443"
|
||||
"8123:8123"
|
||||
"19132:19132/udp"
|
||||
"25500-25600:25500-25600"
|
||||
];
|
||||
volumes = [
|
||||
"./docker/backups:/crafty/backups"
|
||||
"./docker/logs:/crafty/logs"
|
||||
"./docker/servers:/crafty/servers"
|
||||
"./docker/config:/crafty/app/config"
|
||||
"./docker/import:/crafty/import"
|
||||
];
|
||||
environment = {
|
||||
"TZ" = "Europe/Paris";
|
||||
#TODO: move to Nix crafty controller bundle
|
||||
crafty-controller = {
|
||||
image = "registry.gitlab.com/crafty-controller/crafty-4:latest";
|
||||
ports = [
|
||||
"8443:8443"
|
||||
"8123:8123"
|
||||
"19132:19132/udp"
|
||||
"25500-25600:25500-25600"
|
||||
];
|
||||
volumes = [
|
||||
"${cfg.minecraft.path}/docker/backups:/crafty/backups"
|
||||
"${cfg.minecraft.path}/docker/logs:/crafty/logs"
|
||||
"${cfg.minecraft.path}/docker/servers:/crafty/servers"
|
||||
"${cfg.minecraft.path}/docker/config:/crafty/app/config"
|
||||
"${cfg.minecraft.path}/docker/import:/crafty/import"
|
||||
];
|
||||
environment = {
|
||||
"TZ" = "Europe/Paris";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
10
features/freshrss.nix
Normal file
10
features/freshrss.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
services.freshrss = {
|
||||
enable = true;
|
||||
language = "fr";
|
||||
database = {
|
||||
type = "sqlite";
|
||||
};
|
||||
};
|
||||
}
|
13
features/grafana.nix
Normal file
13
features/grafana.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{ }:
|
||||
{
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
http_addr = "127.0.0.1";
|
||||
http_port = 3000;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
|
@ -7,22 +7,66 @@
|
|||
|
||||
with lib;
|
||||
let
|
||||
|
||||
ip = config.homelab-dashboard.defaultAddress;
|
||||
cfg = config.homepage-dashboard;
|
||||
ip = cfg.baseURL;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
homelab-dashboard.defaultAddress = mkOption { type = types.str; };
|
||||
homelab-dashboard.proxmoxVEIp = mkOption { type = types.str; };
|
||||
homelab-dashboard.proxmoxBSIp = mkOption { type = types.str; };
|
||||
homelab-dashboard.baseURL = mkOption {
|
||||
type = types.str;
|
||||
default = "192.168.1.177";
|
||||
};
|
||||
homelab-dashboard.proxmoxVEIp = mkOption {
|
||||
type = types.str;
|
||||
default = "192.168.1.10";
|
||||
};
|
||||
homelab-dashboard.proxmoxBSIp = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
homelab-dashboard.piholeURL = mkOption {
|
||||
type = types.str;
|
||||
default = "192.168.1.25";
|
||||
};
|
||||
};
|
||||
|
||||
#TODO: add Radarr/Sonarr/... api key support
|
||||
config = {
|
||||
sops.defaultSopsFile = ./secrets/services-keys.json;
|
||||
sops.secrets.service-key = {
|
||||
sonarr = { };
|
||||
radarr = { };
|
||||
jellyfin = { };
|
||||
jellyseerr = { };
|
||||
pihole = { };
|
||||
transmission = { };
|
||||
prowlarr = { };
|
||||
proxmoxPassword = { };
|
||||
proxmoxUsername = { };
|
||||
};
|
||||
|
||||
services.homepage-dashboard = {
|
||||
enable = true;
|
||||
settings = {
|
||||
"headerStyle" = "boxed";
|
||||
"language" = "fr";
|
||||
};
|
||||
widgets = [
|
||||
{
|
||||
resources = {
|
||||
cpu = true;
|
||||
disk = "/";
|
||||
memory = true;
|
||||
};
|
||||
}
|
||||
{
|
||||
search = {
|
||||
provider = "duckduckgo";
|
||||
target = "_blank";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
services = [
|
||||
{
|
||||
"Divertissement" = [
|
||||
|
@ -31,6 +75,11 @@ in
|
|||
icon = "jellyfin";
|
||||
description = "Permet de regarder ou écouter du contenu.";
|
||||
href = "http://${ip}:8096/";
|
||||
widget = {
|
||||
type = "jellyfin";
|
||||
url = "http://${ip}:8096";
|
||||
key = config.sops.service-key.jellyfin;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
|
@ -40,6 +89,12 @@ in
|
|||
href = "http://${ip}:8083";
|
||||
};
|
||||
}
|
||||
{
|
||||
"Serveur Minecraft poulet" = {
|
||||
icon = "minecraft";
|
||||
description = "serveur des trois poulets";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
|
@ -49,6 +104,12 @@ in
|
|||
icon = "jellyseerr";
|
||||
description = "Moteur de recherche de films/séries";
|
||||
href = "http://${ip}:5055";
|
||||
|
||||
widget = {
|
||||
type = "jellyseerr";
|
||||
url = "http://${ip}:5055";
|
||||
key = config.sops.secrets.service-key.jellyseerr;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
|
@ -63,6 +124,11 @@ in
|
|||
icon = "readarr";
|
||||
description = "Moteur de recherche de livres";
|
||||
href = "http://${ip}:8787/";
|
||||
widget = {
|
||||
type = "readarr";
|
||||
url = "http://$ip:8787";
|
||||
key = config.sops.secrets.service-key.readarr;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
|
@ -70,6 +136,10 @@ in
|
|||
icon = "prowlarr";
|
||||
description = "Indexe les différents sites de téléchargement";
|
||||
href = "http://${ip}:9696/";
|
||||
widget = {
|
||||
type = "prowlarr";
|
||||
key = config.sops.secrets.service-key.prowlarr;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
|
@ -78,6 +148,10 @@ in
|
|||
icon = "sonarr";
|
||||
description = "Moteur de recherche pour les séries";
|
||||
href = "http://${ip}:8989";
|
||||
widget = {
|
||||
type = "sonarr";
|
||||
key = config.sops.secrets.service-key.sonarr;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
|
@ -85,6 +159,10 @@ in
|
|||
icon = "radarr";
|
||||
description = "Moteur de recherche pour les films";
|
||||
href = "http://${ip}:7878";
|
||||
widget = {
|
||||
type = "radarr";
|
||||
key = config.sops.secrets.service-key.radarr;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
|
@ -93,6 +171,9 @@ in
|
|||
icon = "transmission";
|
||||
description = "s'occupe du téléchargement des fichiers";
|
||||
href = "http://${ip}:9091";
|
||||
widget = {
|
||||
type = "transmission";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
@ -118,15 +199,59 @@ in
|
|||
}
|
||||
{
|
||||
"Administration" = [
|
||||
/*
|
||||
{
|
||||
"Proxmox Backup Server" = {
|
||||
icon = "proxmox-light";
|
||||
description = "Permet de sauvegarder le serveur.";
|
||||
href = "https://${cfg.proxmoxBSIp}:8007";
|
||||
};
|
||||
}
|
||||
*/
|
||||
{
|
||||
"Proxmox Backup Server" = {
|
||||
description = "Permet de sauvegarder le serveur.";
|
||||
"Proxmox VE" = {
|
||||
icon = "proxmox";
|
||||
description = "Panneau de controle des machines virtuelles";
|
||||
href = "https://${cfg.proxmoxVEIp}:8006";
|
||||
widget = {
|
||||
type = "proxmox";
|
||||
username = config.sops.secrets.service-key.proxmoxUsername;
|
||||
key = config.sops.secrets.service-key.proxmoxPassword;
|
||||
url = "https://${cfg.proxmoxVEIp}:8006";
|
||||
node = "pve";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
{
|
||||
"Pi.hole" = {
|
||||
icon = "pihole";
|
||||
description = "Bloqueur de pubs DNS/DHCP";
|
||||
href = "http://${cfg.piholeURL}";
|
||||
widget = {
|
||||
type = "pihole";
|
||||
key = config.sops.secrets.service-key.pihole;
|
||||
url = "http://${cfg.piholeURL}";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
"Grafana" = {
|
||||
icon = "grafana";
|
||||
description = "Visualiseur de graphiques";
|
||||
href = "";
|
||||
};
|
||||
}
|
||||
{
|
||||
"InfluxDB" = {
|
||||
description = "Traite les statistiques du serveur Proxmox";
|
||||
|
||||
"Proxmox VE" = { };
|
||||
};
|
||||
}
|
||||
{
|
||||
"Uptime Kuma" = {
|
||||
icon = "uptimekuma";
|
||||
description = "Surveille l'état des différents services";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@ -134,5 +259,4 @@ in
|
|||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,33 +1,57 @@
|
|||
{ username, driveMountPoint }:
|
||||
|
||||
{ lib }:
|
||||
with lib;
|
||||
# TODO: add access to series and TV folders.
|
||||
let
|
||||
cfg = config.samba;
|
||||
in
|
||||
{
|
||||
# enable samba
|
||||
services.samba = {
|
||||
enable = true;
|
||||
securityType = "user";
|
||||
openFirewall = true;
|
||||
extraConfig = ''
|
||||
workgroup = WORKGROUP
|
||||
server string = hyperserver
|
||||
netbios name = hyperserver
|
||||
security = user
|
||||
'';
|
||||
shares = {
|
||||
music = {
|
||||
path = "${driveMountPoint}/Music";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
"force user" = username;
|
||||
};
|
||||
ebooks = {
|
||||
path = "${driveMountPoint}/Ebooks";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
"force user" = username;
|
||||
options.samba = {
|
||||
dir = mkOption {
|
||||
type = types.str;
|
||||
default = "/srv/Multimedia";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
|
||||
services.samba = {
|
||||
enable = true;
|
||||
securityType = "user";
|
||||
openFirewall = true;
|
||||
extraConfig = ''
|
||||
workgroup = WORKGROUP
|
||||
server string = hyperserver
|
||||
netbios name = hyperserver
|
||||
security = user
|
||||
'';
|
||||
shares = {
|
||||
music = {
|
||||
path = "${cfg.dir}/Music";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
};
|
||||
ebooks = {
|
||||
path = "${cfg.dir}/Ebooks";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
};
|
||||
movies = {
|
||||
path = "${cfg.dir}/Films";
|
||||
browseable = "yes";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
"read only" = "no";
|
||||
};
|
||||
shows = {
|
||||
path = "${cfg.dir}/SeriesTV";
|
||||
"read only" = "no";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
browseable = "yes";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
18
features/searx.nix
Normal file
18
features/searx.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ config }:
|
||||
{
|
||||
sops.secrets."searx" = {
|
||||
sopsFile = ./secrets/searx.env;
|
||||
format = "dotenv";
|
||||
};
|
||||
|
||||
services.searx = {
|
||||
enable = true;
|
||||
redisCreateLocally = true;
|
||||
settings = {
|
||||
server.port = 8080;
|
||||
server.secret_key = builtins.toJSON config.sops.secrets."searx";
|
||||
|
||||
server.bind_address = "0.0.0.0";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -6,7 +6,10 @@ let
|
|||
in
|
||||
{
|
||||
options = {
|
||||
slskd.directory = mkOption { type = types.str; };
|
||||
slskd.directory = mkOption {
|
||||
type = types.str;
|
||||
default = "/srv/Multimedia/Music";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
|
||||
|
@ -14,16 +17,17 @@ in
|
|||
sopsFile = ./secrets/slskd.env;
|
||||
format = "dotenv";
|
||||
};
|
||||
|
||||
services.slskd = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
environmentFile = config.sops.secrets."slskd".path;
|
||||
domain = null;
|
||||
settings = {
|
||||
shares.directories = [ "${cfg.slskd.directory}/Music" ];
|
||||
shares.directories = [ "${cfg.slskd.directory}" ];
|
||||
soulseek.description = "i luv katz n mewsik";
|
||||
directories.files.downloads = "${cfg.slskd.directory}/Music/clean";
|
||||
directories.files.incomplete = "${cfg.slskd.directory}/Music/incomplete";
|
||||
directories.files.downloads = "${cfg.slskd.directory}/clean";
|
||||
directories.files.incomplete = "${cfg.slskd.directory}/incomplete";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
4
features/synapse-matrix.nix
Normal file
4
features/synapse-matrix.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
{ }:
|
||||
#TODO: implement
|
||||
{
|
||||
}
|
|
@ -6,7 +6,10 @@ let
|
|||
in
|
||||
{
|
||||
options.transmission = {
|
||||
directory = mkOption { type = lib.types.str; };
|
||||
directory = mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/srv/Multimedia";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
|
10
features/uptime-kuma.nix
Normal file
10
features/uptime-kuma.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
{ }:
|
||||
{
|
||||
#TODO: implement uptime-kama
|
||||
services.uptime-kama = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PORT = "4000";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -7,18 +7,23 @@
|
|||
let
|
||||
ip = "192.168.1.177";
|
||||
gateway = "192.168.1.1";
|
||||
driveMountPoint = "/srv/Multimedia";
|
||||
username = "homelab";
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./features/authentik.nix
|
||||
./features/slskd.nix
|
||||
./features/arr-suite.nix
|
||||
./features/samba-shares.nix
|
||||
./features/authentik.nix
|
||||
./features/calibre-web.nix
|
||||
./features/containers.nix
|
||||
./features/freshrss.nix
|
||||
./features/grafana.nix
|
||||
./features/homelab-dashboard.nix
|
||||
./features/samba-shares.nix
|
||||
./features/searx.nix
|
||||
# ./features/synapse-matrix.nix
|
||||
./features/slskd.nix
|
||||
./features/transmission.nix
|
||||
./features/uptime-kuma.nix
|
||||
];
|
||||
|
||||
# setting up networking!!
|
||||
|
@ -43,14 +48,23 @@ in
|
|||
enable = true;
|
||||
allowedTCPPorts = [
|
||||
22
|
||||
5030
|
||||
8080
|
||||
9091
|
||||
5030 # slskd
|
||||
8080 # searxng
|
||||
8083 # calibre-web
|
||||
8443 # crafty-controller
|
||||
9091 # transmission
|
||||
];
|
||||
allowedUDPPorts = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
#TODO: setup fail2ban
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
ignoreIP = [ "192.168.1.0/24" ];
|
||||
extraPackages = [ ];
|
||||
jails = { };
|
||||
};
|
||||
users.groups.multimedia = {
|
||||
members = [
|
||||
"slskd"
|
||||
|
@ -59,6 +73,7 @@ in
|
|||
"sonarr"
|
||||
"transmission"
|
||||
"jellyfin"
|
||||
"bazarr"
|
||||
username
|
||||
];
|
||||
};
|
||||
|
@ -70,11 +85,6 @@ in
|
|||
# define your secrets with
|
||||
# `nix-shell -p sops --run "sops ./secrets/yoursecret.env"`
|
||||
|
||||
sops.secrets."searx" = {
|
||||
sopsFile = ./secrets/searx.env;
|
||||
format = "dotenv";
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
jellyfin
|
||||
jellyfin-web
|
||||
|
@ -87,6 +97,7 @@ in
|
|||
jellyseerr
|
||||
homepage-dashboard
|
||||
slskd
|
||||
bazarr
|
||||
];
|
||||
|
||||
services.jellyfin = {
|
||||
|
@ -94,38 +105,10 @@ in
|
|||
openFirewall = true;
|
||||
};
|
||||
|
||||
# -arr suite
|
||||
|
||||
services.searx = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server.secret_key = builtins.toJSON config.sops.secrets."searx";
|
||||
};
|
||||
};
|
||||
|
||||
services.calibre-web = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
options = {
|
||||
enableBookUploading = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
virtualHosts.":80".extraConfig = ''
|
||||
virtualHosts."homelab.localhost".extraConfig = ''
|
||||
reverse_proxy :8082
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
services.photoprism = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PHOTOPRISM_DEFAULT_LOCALE = "fr";
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue