many changes

This commit is contained in:
2025-01-26 10:55:38 +01:00
parent 12ef36af33
commit a2d482e16d
98 changed files with 419 additions and 27402 deletions

View File

@@ -1,36 +0,0 @@
{
lib,
pkgs,
...
}: let
create_users = host: {
users.users."${host.username}" = {
createHome = false;
home = "/home/chroot/" + host.username;
isNormalUser = false;
isSystemUser = true;
group = "sftp_users";
openssh.authorizedKeys.keys = [host.key];
shell = null;
};
};
users = [
{
username = "notebook";
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7";
}
];
in {
imports = builtins.map create_users users;
users.groups = {sftp_users = {};};
services.openssh.extraConfig = ''
Match Group sftp_users
X11Forwarding no
AllowTcpForwarding no
ChrootDirectory %h
ForceCommand internal-sftp
'';
}

View File

@@ -1,116 +0,0 @@
{
pkgs,
config,
...
}: let
ldapConfig = {
vaultwarden_url = "https://bitwarden.cloonar.com";
vaultwarden_admin_token = "@ADMIN_TOKEN@";
ldap_host = "localhost";
ldap_bind_dn = "cn=vmail,dc=cloonar,dc=com";
ldap_bind_password = "@LDAP_PASSWORD@";
ldap_search_base_dn = "dc=cloonar,dc=com";
ldap_search_filter = "(&(objectClass=inetOrgPerson))";
ldap_sync_interval_seconds = 3600;
};
ldapConfigFile =
pkgs.runCommand "config.toml"
{
buildInputs = [pkgs.remarshal];
preferLocalBuild = true;
} ''
remarshal -if json -of toml \
< ${pkgs.writeText "config.json" (builtins.toJSON ldapConfig)} \
> $out
'';
in {
packageOverrides = pkgs: {
nur = import (builtins.fetchTarball "https://github.com/nix-community/NUR/archive/master.tar.gz") {
inherit pkgs;
};
};
environment.systemPackages = with pkgs; [
nur.repos.mic92.vaultwarden_ldap
];
services.vaultwarden = {
enable = true;
dbBackend = "mysql";
config = {
domain = "https://bitwarden.cloonar.com";
signupsAllowed = false;
rocketPort = 3011;
databaseUrl = "mysql://bitwarden:<${config.sops.secrets.bitwarden-db-password.path}@localhost/bitwarden";
enableDbWal = "false";
websocketEnabled = true;
smtpHost = "smtp.cloonar.com";
smtpFrom = "bitwarden@cloonar.com";
smtpUsername = "bitwarden@cloonar.com";
};
};
systemd.services.vaultwarden.serviceConfig = {
EnvironmentFile = [config.sops.secrets.bitwarden-smtp-password.path];
};
systemd.services.vaultwarden_ldap = {
wantedBy = ["multi-user.target"];
preStart = ''
sed \
-e "s=@LDAP_PASSWORD@=$(<${config.sops.secrets.bitwarden-ldap-password.path})=" \
-e "s=@ADMIN_TOKEN@=$(<${config.sops.secrets.bitwarden-admin-token.path})=" \
${ldapConfigFile} \
> /run/vaultwarden_ldap/config.toml
'';
serviceConfig = {
Restart = "on-failure";
RestartSec = "2s";
ExecStart = "${config.nur.repos.mic92.vaultwarden_ldap}/bin/vaultwarden_ldap";
Environment = "CONFIG_PATH=/run/vaultwarden_ldap/config.toml";
RuntimeDirectory = ["vaultwarden_ldap"];
User = "vaultwarden_ldap";
};
};
services.nginx = {
virtualHosts."bitwarden.cloonar.com" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
extraConfig = ''
client_max_body_size 128M;
'';
locations."/" = {
proxyPass = "http://localhost:3011";
proxyWebsockets = true;
};
locations."/notifications/hub" = {
proxyPass = "http://localhost:3012";
proxyWebsockets = true;
};
locations."/notifications/hub/negotiate" = {
proxyPass = "http://localhost:3011";
proxyWebsockets = true;
};
};
};
sops.secrets = {
bitwarden-admin-token.owner = "vaultwarden_ldap";
bitwarden-ldap-password.owner = "vaultwarden_ldap";
bitwarden-db-password.owner = "vaultwarden";
bitwarden-smtp-password.owner = "vaultwarden";
};
users.users.vaultwarden_ldap = {
isSystemUser = true;
group = "vaultwarden_ldap";
};
users.groups.vaultwarden_ldap = {};
}

View File

@@ -1,38 +0,0 @@
let
# NixOS 22.11 as of 2023-01-12
nixpkgs = builtins.getFlake "github:nixos/nixpkgs/54644f409ab471e87014bb305eac8c50190bcf48";
sys = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
({ config, pkgs, lib, modulesPath, ... }: {
imports = [
(modulesPath + "/installer/netboot/netboot-minimal.nix")
];
config = {
## Some useful options for setting up a new system
# services.getty.autologinUser = lib.mkForce "root";
# users.users.root.openssh.authorizedKeys.keys = [ ... ];
# console.keyMap = "de";
# hardware.video.hidpi.enable = true;
system.stateVersion = config.system.nixos.release;
};
})
];
};
run-pixiecore = let
hostPkgs = if sys.pkgs.system == builtins.currentSystem
then sys.pkgs
else nixpkgs.legacyPackages.${builtins.currentSystem};
build = sys.config.system.build;
in hostPkgs.writers.writeBash "run-pixiecore" ''
exec ${hostPkgs.pixiecore}/bin/pixiecore \
boot ${build.kernel}/bzImage ${build.netbootRamdisk}/initrd \
--cmdline "init=${build.toplevel}/init loglevel=4" \
--debug --dhcp-no-bind \
--port 64172 --status-port 64172 "$@"
'';
in
run-pixiecore

View File

@@ -1,55 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
uuid = "";
cfg = config.services.clevis;
in
{
options.services.clevis = {
uuid = mkOption {
type = types.str;
default = "";
description = lib.mdDoc ''
UUID of device to decrypt with clevis.
'';
};
};
config = {
environment.systemPackages = with pkgs; [
clevis
];
boot.initrd.extraUtilsCommands = ''
# clevis dependencies
copy_bin_and_libs ${pkgs.curl}/bin/curl
copy_bin_and_libs ${pkgs.bash}/bin/bash
copy_bin_and_libs ${pkgs.jose}/bin/jose
# clevis scripts and binaries
for i in ${pkgs.clevis}/bin/* ${pkgs.clevis}/bin/.clevis-wrapped; do
copy_bin_and_libs "$i"
done
'';
boot.initrd.luks.devices."nixos-enc" = {
device = "/dev/disk/by-uuid/${cfg.uuid}";
preOpenCommands = with pkgs; ''
# what would be a sensible way of automating this? at the very least the versions should not be hard coded
ln -s ../.. /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${bash.name}
ln -s ../.. /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${clevis.name}
ln -s ../.. /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${coreutils.name}
# this runs in the background so that /crypt-ramfs/device gets set up, which implies crypt-askpass
# is ready to receive an input which it will write to /crypt-ramfs/passphrase.
# for some reason writing that file directly does not seem to work, which is why the pipe is used.
# the clevis_luks_unlock_device function is equivalent to the clevis-luks-pass command but avoid
# needing to pass the slot argument.
# using clevis-luks-unlock directly can successfully open the luks device but requires the name
# argument to be passed and will not be detected by the stage-1 luks root stuff.
bash -e -c 'while [ ! -f /crypt-ramfs/device ]; do sleep 1; done; . /bin/clevis-luks-common-functions; clevis_luks_unlock_device "$(cat /crypt-ramfs/device)" | cryptsetup-askpass' &
'';
};
};
}

View File

@@ -1,28 +0,0 @@
{ config, pkgs, ... }:
{
hardware.pulseaudio.enable = false;
services.xserver = {
enable = true;
libinput.enable = true;
displayManager.gdm.enable = true;
displayManager.defaultSession = "sway";
desktopManager.gnome = {
enable = true;
extraGSettingsOverrides = ''
[org.gnome.desktop.interface]
gtk-theme='Dracula'
'';
};
};
environment.systemPackages = with pkgs; [
dracula-theme
gnome.gnome-tweaks
gnome.dconf-editor
gnomeExtensions.vitals
gnomeExtensions.forge
];
}

View File

@@ -1,15 +0,0 @@
{
services.gogs = {
enable = true;
domain = "git.cloonar.com";
rootUrl = "http://git.cloonar.com/";
httpAddress = "git.cloonar.com";
httpPort = 3000;
extraConfig = ''
[server]
EXTERNAL_URL = http://git.cloonar.com/
[auth]
DISABLE_REGISTRATION = true
'';
};
}

View File

@@ -1,90 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.howdy;
ircfg = config.services.ir-toggle;
# `dark_threshold` is required for X1 Carbon 7th to work
configINI = pkgs.runCommand "config.ini" { } ''
cat ${cfg.package}/lib/security/howdy/config.ini > $out
substituteInPlace $out --replace 'device_path = none' 'device_path = ${cfg.device}'
substituteInPlace $out --replace 'dark_threshold = 50' 'dark_threshold = ${
toString cfg.dark-threshold
}'
substituteInPlace $out --replace 'certainty = 3.5' 'certainty = ${
toString cfg.certainty
}'
'';
pam-rule = pkgs.lib.mkDefault (pkgs.lib.mkBefore
"auth sufficient ${pkgs.pam_python}/lib/security/pam_python.so ${config.services.howdy.package}/lib/security/howdy/pam.py");
in {
options = {
services.ir-toggle = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable Chicony IR Emitter toggler.
'';
};
};
services.howdy = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable howdy and PAM module for face recognition.
'';
};
package = mkOption {
type = types.package;
default = pkgs.howdy;
defaultText = "pkgs.howdy";
description = ''
Howdy package to use.
'';
};
device = mkOption {
type = types.path;
default = "/dev/video0";
description = ''
Device file connected to the IR sensor.
'';
};
certainty = mkOption {
type = types.int;
default = 3.5;
description = ''
The certainty of the detected face belonging to the user of the account. On a scale from 1 to 10, values above 5 are not recommended.
'';
};
dark-threshold = mkOption {
type = types.int;
default = 50;
description = ''
Because of flashing IR emitters, some frames can be completely unlit. Skip the frame if the lowest 1/8 of the histogram is above this percentage of the total. The lower this setting is, the more dark frames are ignored.
'';
};
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ cfg.package pkgs.ir_toggle ];
environment.etc."howdy/config.ini".source = configINI;
security.pam.services = {
sudo.text = pam-rule; # Sudo
login.text = pam-rule; # User login
polkit-1.text = pam-rule; # PolKit
i3lock.text = pam-rule; # i3lock
};
powerManagement.resumeCommands =
"${pkgs.ir_toggle}/bin/chicony-ir-toggle on";
services.udev.packages = [ pkgs.ir_toggle ];
};
}

View File

@@ -1,45 +0,0 @@
{
core = {
detection_notice = false;
timeout_notice = true;
no_confirmation = false;
suppress_unknown = false;
abort_if_ssh = true;
abort_if_lid_closed = true;
disabled = false;
use_cnn = false;
workaround = "off";
};
video = {
certainty = 3.5;
timeout = 4;
device_path = "/dev/video2";
warn_no_device = true;
max_height = 320;
frame_width = -1;
frame_height = -1;
dark_threshold = 60;
recording_plugin = "opencv";
device_format = "v4l2";
force_mjpeg = false;
exposure = -1;
rotate = 0;
};
snapshots = {
save_failed = false;
save_successful = false;
};
rubberstamps = {
enabled = false;
stamp_rules = "nod 5s failsafe min_distance=12";
};
debug = {
end_report = false;
verbose_stamps = false;
gtk_stdout = false;
};
}

View File

@@ -1,123 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
pam-rule = pkgs.lib.mkDefault (pkgs.lib.mkBefore
''
auth sufficient pam_unix.so try_first_pass nullok
auth sufficient ${config.services.howdy.package}/lib/security/pam_howdy.so
'');
pam-sudo-rule = pkgs.lib.mkDefault (pkgs.lib.mkBefore
''
auth sufficient ${config.services.howdy.package}/lib/security/pam_howdy.so
'');
cfg = config.services.howdy;
irCfg = config.services.linux-enable-ir-emitter;
settingsType = pkgs.formats.ini { };
in {
options = {
services.howdy = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable howdy and PAM module for face recognition.
'';
};
package = mkOption {
type = types.package;
default = pkgs.howdy;
defaultText = "pkgs.howdy";
description = ''
Howdy package to use.
'';
};
settings = mkOption {
inherit (settingsType) type;
default = import ./config.nix;
description = mdDoc ''
Howdy configuration file. Refer to
<https://github.com/boltgolt/howdy/blob/beta/howdy/src/config.ini>
for options.
'';
};
};
services.linux-enable-ir-emitter = {
enable = mkEnableOption (mdDoc "") // {
description = mdDoc ''
Whether to enable IR emitter hardware. Designed to be used with the
Howdy facial authentication. After enabling the service, configure
the emitter with `sudo linux-enable-ir-emitter configure`.
'';
};
package = mkPackageOptionMD pkgs "linux-enable-ir-emitter" {} // {
description = mdDoc ''
Package to use for the Linux Enable IR Emitter service.
'';
};
device = mkOption {
type = types.str;
default = "video2";
description = mdDoc ''
IR camera device to depend on. For example, for `/dev/video2`
the value would be `video2`. Find this with the command
{command}`realpath /dev/v4l/by-path/<generated-driver-name>`.
'';
};
};
};
config = mkIf cfg.enable {
# environment.systemPackages = [ cfg.package pkgs.ir_toggle ];
# environment.etc."howdy/config.ini".source = configINI;
# security.pam.services = {
# sudo.text = pam-rule; # Sudo
# login.text = pam-rule; # User login
# polkit-1.text = pam-rule; # PolKit
# i3lock.text = pam-rule; # i3lock
# };
# powerManagement.resumeCommands =
# "${pkgs.ir_toggle}/bin/chicony-ir-toggle on";
# services.udev.packages = [ pkgs.ir_toggle ];
environment.systemPackages = [ cfg.package irCfg.package ];
security.pam.services = {
sudo.text = pam-sudo-rule; # Sudo
login.text = pam-rule; # User login
polkit-1.text = pam-rule; # PolKit
swaylock.text = pam-rule; # i3lock
# gdm-password.text = pam-rule; # i3lock
};
systemd.services.linux-enable-ir-emitter = rec {
description = "Enable the infrared emitter";
script = "${getExe irCfg.package} run";
wantedBy = [
"multi-user.target"
"suspend.target"
"hybrid-sleep.target"
"hibernate.target"
"suspend-then-hibernate.target"
];
after = wantedBy ++ [ "dev-${irCfg.device}.device" ];
};
systemd.tmpfiles.rules = [
"d /var/lib/linux-enable-ir-emitter 0755 root root - -"
];
environment.etc."linux-enable-ir-emitter".source = "/var/lib/linux-enable-ir-emitter";
environment.etc."howdy/config.ini".source = settingsType.generate "howdy-config.ini" cfg.settings;
};
}

View File

@@ -1,22 +0,0 @@
{ config, pkgs, callPackage, ... }:
{
environment.pathsToLink = [ "/libexec" ]; # links /libexec from derivations to /run/current-system/sw
services.xserver = {
enable = true;
desktopManager = {
xterm.enable = false;
};
windowManager.i3 = {
enable = true;
extraPackages = with pkgs; [
dmenu #application launcher most people use
i3status # gives you the default i3 status bar
i3lock #default i3 screen locker
i3blocks #if you are planning on using i3blocks over i3status
];
};
};
}

View File

@@ -1,21 +0,0 @@
{ config, ... }: {
services.influxdb = {
enable = true;
extraConfig = {
http = {
auth-enabled = true;
log-enabled = false;
https-enabled = true;
https-certificate = "/var/lib/acme/influxdb.cloonar.com/fullchain.pem";
https-private-key = "/var/lib/acme/influxdb.cloonar.com/key.pem";
};
};
};
networking.firewall.allowedTCPPorts = [ 8086 ];
security.acme.certs."influxdb.cloonar.com" = {
postRun = "systemctl restart influxdb.service";
group = "influxdb";
};
}

View File

@@ -1,78 +0,0 @@
{ pkgs, ... }:
let
mysqlCreateDatabase = pkgs.writeShellScriptBin "mysql-create-database" ''
#!/usr/bin/env bash
if [ $# -lt 2 ]
then
echo "Usage: $0 <database> <host>"
exit 1
fi
if ! [ $EUID -eq 0 ]
then
echo "Must be root!" >&2
exit 1
fi
DB="$1"
HOST="$2"
PASSWORD="$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64 | xargs)"
cat <<EOF | mysql --host localhost --user root
create database $DB;
grant usage on $DB.* to '$DB'@'$HOST' identified by '$PASSWORD';
grant all privileges on $DB.* to '$DB'@'$HOST';
EOF
echo
echo "Password for user $DB is:"
echo
echo $PASSWORD
echo
'';
mysqlDeleteDatabase = pkgs.writeShellScriptBin "mysql-delete-database" ''
#!/usr/bin/env bash
if [ $# -lt 1 ]
then
echo "Usage: $0 <database>"
exit 1
fi
if ! [ $EUID -eq 0 ]
then
echo "Must be root!" >&2
exit 1
fi
DB="$1"
PASSWORD="$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64 | xargs)"
cat <<EOF | mysql --host localhost --user root
drop database $DB;
drop user '$DB';
EOF
echo
echo "Dropped database $DB!"
echo
'';
in {
environment.systemPackages = [
mysqlCreateDatabase
mysqlDeleteDatabase
];
services.mysql = {
enable = true;
package = pkgs.mariadb;
settings = {
mysqld = {
max_allowed_packet = "64M";
};
};
};
services.mysqlBackup.enable = true;
services.mysqlBackup.databases = [ "mysql" ];
}

View File

@@ -1,13 +0,0 @@
{ pkgs, ... }:
let
mysql-scripts = pkgs.callPackage ./pkgs/mysql-scripts.nix {};
in {
environment.systemPackages = [
mysql-scripts
];
services.mysql = {
enable = true;
package = pkgs.mariadb;
};
}

View File

@@ -1,14 +0,0 @@
{
stdenv,
lib,
bash,
}:
stdenv.mkDerivation {
name = "mysql-scripts";
src = ./scripts;
buildInputs = [ bash ];
#nativeBuildInputs = [lib.makeWrapper];
installPhase = ''
install -D --target $out/bin *
'';
}

View File

@@ -1,28 +0,0 @@
#!/usr/bin/env bash
if [ $# -lt 1 ]
then
echo "Usage: $0 <database>"
exit 1
fi
if ! [ $EUID -eq 0 ]
then
echo "Must be root!" >&2
exit 1
fi
DB="$1"
PASSWORD="$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64 | xargs)"
cat <<EOF | mysql --host localhost --user root
create database $DB;
grant usage on $DB.* to '$DB'@'%' identified by '$PASSWORD';
grant all privileges on $DB.* to '$DB'@'%';
EOF
echo
echo "Password for user $DB is:"
echo
echo $PASSWORD
echo

View File

@@ -1,25 +0,0 @@
#!/usr/bin/env bash
if [ $# -lt 1 ]
then
echo "Usage: $0 <database>"
exit 1
fi
if ! [ $EUID -eq 0 ]
then
echo "Must be root!" >&2
exit 1
fi
DB="$1"
PASSWORD="$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64 | xargs)"
cat <<EOF | mysql --host localhost --user root
drop database $DB;
drop user '$DB';
EOF
echo
echo "Dropped database $DB!"
echo

View File

@@ -1,135 +0,0 @@
{ pkgs, lib, config, ... }:
let
domain = "cloonar.dev";
dataDir = "/var/www/${domain}";
in {
systemd.services."phpfpm-${domain}".serviceConfig.ProtectHome = lib.mkForce false;
services.phpfpm.pools."${domain}" = {
user = domain;
settings = {
"listen.owner" = config.services.nginx.user;
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = true;
"catch_workers_output" = true;
"access.log" = "/var/log/$pool.access.log";
};
phpPackage = pkgs.php81;
phpEnv."PATH" = lib.makeBinPath [ pkgs.php81 ];
};
services.nginx.virtualHosts."cloonar.dev" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
root = "${dataDir}";
locations."/favicon.ico".extraConfig = ''
log_not_found off;
access_log off;
'';
# TYPO3 - Rule for versioned static files, configured through:
# - $GLOBALS['TYPO3_CONF_VARS']['BE']['versionNumberInFilename']
# - $GLOBALS['TYPO3_CONF_VARS']['FE']['versionNumberInFilename']
extraConfig = ''
if (!-e $request_filename) {
rewrite ^/(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ /$1.$3 last;
}
'';
# TYPO3 - Block access to composer files
locations."~* composer\.(?:json|lock)".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to flexform files
locations."~* flexform[^.]*\.xml".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to language files
locations."~* locallang[^.]*\.(?:xml|xlf)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to static typoscript files
locations."~* ext_conf_template\.txt|ext_typoscript_constants\.txt|ext_typoscript_setup\.txt".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to miscellaneous protected files
locations."~* /.*\.(?:bak|co?nf|cfg|ya?ml|ts|typoscript|tsconfig|dist|fla|in[ci]|log|sh|sql|sqlite)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to recycler and temporary directories
locations."~ _(?:recycler|temp)_/".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to configuration files stored in fileadmin
locations."~ fileadmin/(?:templates)/.*\.(?:txt|ts|typoscript)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to libraries, source and temporary compiled data
locations."~ ^(?:vendor|typo3_src|typo3temp/var)".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to protected extension directories
locations."~ (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|Resources/Private|Tests?|Documentation|docs?)/".extraConfig = ''
deny all;
'';
locations."/".extraConfig = ''
index index.php index.html;
try_files $uri $uri/ /index.php$is_args$args;
'';
# TYPO3 Backend URLs
locations."/typo3".extraConfig = ''
rewrite ^ /typo3/;
'';
locations."/typo3/".extraConfig = ''
try_files $uri /typo3/index.php$is_args$args;
'';
locations."~ [^/]\.php(/|$)".extraConfig = ''
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 16k;
fastcgi_connect_timeout 240s;
fastcgi_read_timeout 240s;
fastcgi_send_timeout 240s;
fastcgi_pass unix:${config.services.phpfpm.pools."${domain}".socket};
fastcgi_index index.php;
'';
};
users.users."${domain}" = {
isSystemUser = true;
createHome = true;
home = dataDir;
homeMode= "770";
#home = "/home/${domain}";
group = "nginx";
};
users.groups.${domain} = {};
}

View File

@@ -1,55 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
./cloonar.dev.nix
];
environment.systemPackages = with pkgs; [
imagemagick
ghostscript
];
systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
commonHttpConfig = ''
# Add HSTS header with preloading to HTTPS requests.
# Adding this header to HTTP requests is discouraged
map $scheme $hsts_header {
https "max-age=31536000; includeSubdomains; preload";
}
add_header Strict-Transport-Security $hsts_header;
# Enable CSP for your services.
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
# Minimize information leaked to other domains
add_header 'Referrer-Policy' 'origin-when-cross-origin';
# Disable embedding as a frame
add_header X-Frame-Options DENY;
# Prevent injection of code in other mime types (XSS Attacks)
add_header X-Content-Type-Options nosniff;
# Enable XSS protection of the browser.
# May be unnecessary when CSP is configured properly (see above)
add_header X-XSS-Protection "1; mode=block";
# This might create errors
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
'';
};
}

View File

@@ -1,48 +0,0 @@
{ config, ... }:
{
imports = [
./cloonar.dev.nix
];
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
commonHttpConfig = ''
# Add HSTS header with preloading to HTTPS requests.
# Adding this header to HTTP requests is discouraged
map $scheme $hsts_header {
https "max-age=31536000; includeSubdomains; preload";
}
add_header Strict-Transport-Security $hsts_header;
# Enable CSP for your services.
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
# Minimize information leaked to other domains
add_header 'Referrer-Policy' 'origin-when-cross-origin';
# Disable embedding as a frame
add_header X-Frame-Options DENY;
# Prevent injection of code in other mime types (XSS Attacks)
add_header X-Content-Type-Options nosniff;
# Enable XSS protection of the browser.
# May be unnecessary when CSP is configured properly (see above)
add_header X-XSS-Protection "1; mode=block";
# This might create errors
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
'';
};
}

View File

@@ -1,2 +0,0 @@
#(import <nixpkgs> {}).callPackage (builtins.fetchurl "https://raw.githubusercontent.com/delroth/infra.delroth.net/master/pkgs/parsec.nix") {}
#(import <nixpkgs> {}).callPackage (builtins.fetchurl "https://raw.githubusercontent.com/delroth/infra.delroth.net/38a040e4bbfef7ee13c4b0a75dc79c77ddfdc759/pkgs/parsec.nix") {}

View File

@@ -1,112 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.room-assistant;
in
{
options = {
services.room-assistant = {
enable = mkEnableOption (lib.mdDoc "room-assistant");
name = mkOption {
type = with types; uniq string;
description = "
...
";
default = "room";
};
mqttHost = mkOption {
type = with types; uniq string;
description = "
...
";
default = "";
};
mqttUser = mkOption {
type = with types; uniq string;
description = "
...
";
default = "espresense";
};
mqttPassword = mkOption {
type = with types; uniq string;
description = "
...
";
default = "insecure-password";
};
};
};
config = mkIf cfg.enable {
hardware = {
bluetooth.enable = true;
deviceTree.filter = "bcm2711-rpi-*.dtb";
};
systemd.services = {
btattach = {
before = [ "bluetooth.service" ];
after = [ "dev-ttyAMA0.device" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.bluez}/bin/btattach -B /dev/ttyAMA0 -P bcm -S 3000000";
};
};
};
virtualisation.docker.enable = true;
environment.etc."room-assistant.yml" = {
text = ''
global:
instanceName: ${cfg.name}
integrations:
- homeAssistant
- bluetoothClassic
homeAssistant:
mqttUrl: 'mqtt://${cfg.mqttHost}'
mqttOptions:
username: ${cfg.mqttUser}
password: ${cfg.mqttPassword}
bluetoothClassic:
addresses:
- A8:5B:B7:98:84:F0
- 00:24:E4:E6:FE:AD
'';
# The UNIX file mode bits
mode = "0440";
};
systemd.services."room-assistant" = {
description = "room-assistant";
wantedBy = [ "multi-user.target" ];
after = [ "docker.service" "docker.socket" ];
requires = [ "docker.service" "docker.socket" ];
script = ''
exec ${pkgs.docker}/bin/docker run \
--rm \
--name=room-assistant \
--network=host \
-v /var/run/dbus:/var/run/dbus \
-v /etc/room-assistant.yml:/room-assistant/config/local.yml \
--cap-add=NET_ADMIN \
mkerix/room-assistant:2.20.0
'';
preStop = "${pkgs.docker}/bin/docker stop room-assistant";
reload = "${pkgs.docker}/bin/docker restart room-assistant";
serviceConfig = {
ExecStartPre = "-${pkgs.docker}/bin/docker rm -f room-assistant";
ExecStopPost = "-${pkgs.docker}/bin/docker rm -f room-assistant";
TimeoutStartSec = 0;
TimeoutStopSec = 120;
Restart = "always";
};
};
};
}

View File

@@ -1,22 +0,0 @@
{ pkgs, ... }:
let
domain = "mail-test.cloonar.com";
in
{
services.roundcube = {
enable = true;
hostName = "${domain}";
extraConfig = ''
$config['imap_host'] = 'tls://imap-test.cloonar.com';
$config['smtp_server'] = "tls://mail-test.cloonar.com";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
'';
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
};
}

View File

@@ -1,118 +0,0 @@
{ pkgs, lib, config, ... }:
let
domain = "self-service.cloonar.com";
php = pkgs.php82;
version = "1.5.2";
dataDir = "/var/www/${domain}";
in {
environment.systemPackages = with pkgs; [
smarty3
];
systemd.services."phpfpm-${domain}".serviceConfig.ProtectHome = lib.mkForce false;
systemd.services.selfservicepassword_setup = let
overrideConfig = pkgs.writeText "nextcloud-config.php" ''
<?php
$ldap_url = "ldap://ldap-test.cloonar.com:389";
$ldap_starttls = true;
define("SMARTY", "Smarty.class.php");
$use_tokens = false;
$use_sms = false;
'';
in {
wantedBy = [ "multi-user.target" ];
before = [ "phpfpm-${domain}.service" ];
script = ''
mkdir -p ${dataDir}/public
curl -L https://github.com/ltb-project/self-service-password/archive/refs/tags/v${version}.tar.gz > ${dataDir}/package.tar.gz
/run/current-system/sw/bin/tar xf ${dataDir}/package.tar.gz -C ${dataDir}
mv ${dataDir}/self-service-password-${version}/* ${dataDir}/public/
rm -rf ${dataDir}/self-service-password-${version}
cp ${overrideConfig} ${dataDir}/public/conf/config.inc.local.php
'';
path = [ pkgs.gzip pkgs.curl ];
serviceConfig.Type = "oneshot";
serviceConfig.User = domain;
};
services.phpfpm.pools."${domain}" = {
user = domain;
settings = {
"listen.owner" = config.services.nginx.user;
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_flag[display_errors]" = "on";
"php_admin_value[error_log]" = "/var/log/${domain}.error.log";
"php_admin_flag[log_errors]" = "on";
"php_value[include_path]" = ".:/usr/share/php:${pkgs.smarty3}";
"catch_workers_output" = "yes";
"access.log" = "/var/log/$pool.access.log";
};
phpPackage = php;
phpEnv."PATH" = lib.makeBinPath [ php ];
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
root = "${dataDir}/public/htdocs";
locations."/favicon.ico".extraConfig = ''
log_not_found off;
access_log off;
'';
# extraConfig = ''
# if (!-e $request_filename) {
# rewrite ^/(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ /$1.$3 last;
# }
# '';
locations."/".extraConfig = ''
index index.php index.html;
try_files $uri $uri/ /index.php$is_args$args;
'';
locations."~ [^/]\.php(/|$)".extraConfig = ''
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 16k;
fastcgi_connect_timeout 240s;
fastcgi_read_timeout 240s;
fastcgi_send_timeout 240s;
fastcgi_pass unix:${config.services.phpfpm.pools."${domain}".socket};
fastcgi_index index.php;
'';
# locations."~ /\.".extraConfig = ''
# log_not_found off;
# deny all;
# '';
#
# locations."~ /scripts".extraConfig = ''
# log_not_found off;
# deny all;
# '';
};
users.users."${domain}" = {
#isSystemUser = true;
isNormalUser = true;
createHome = true;
home = dataDir;
homeMode= "770";
group = "nginx";
};
users.groups.${domain} = {};
}

View File

@@ -1,38 +0,0 @@
{ config, pkgs, ... }:
{
# security.rtkit.enable = true;
# services.pipewire = {
# enable = true;
# alsa.enable = true;
# alsa.support32Bit = true;
# pulse.enable = true;
#
# };
sound.enable = true;
hardware.pulseaudio.enable = true;
hardware.pulseaudio.support32Bit = true;
services.getty.autologinUser = "snapclient";
users.groups.snapclient = {};
users.users.snapclient = {
isNormalUser = true;
group = "snapclient";
extraGroups = [ "audio" "pipewire" ];
};
systemd.user.services.snapclient = {
wantedBy = [
"default.target"
];
after = [
"network.target"
];
serviceConfig = {
# User = "snapclient";
# Group = "snapclient";
ExecStart = "${pkgs.snapcast}/bin/snapclient -h mopidy.cloonar.com -p 1704 --player pulse";
Restart = "on-failure";
};
};
}

View File

@@ -1,81 +0,0 @@
{ config, pkgs, ... }:
let
user = "tang";
group = "tang";
in {
environment.systemPackages = with pkgs; [
jose
tang
];
systemd.paths.tangd-update = {
pathConfig = {
PathChanged = "/var/db/tang";
MakeDirectory = true;
DirectoryMode = "0700";
};
};
systemd.services.tangd-update = {
description = "Tang update";
path = [ pkgs.jose ];
serviceConfig = {
Type = "oneshot";
StandardError = "journal";
ExecStart = "${pkgs.tang}/libexec/tangd-update /var/db/tang /var/cache/tang";
};
};
systemd.services.tangd-keygen = {
description = "Tang keygen";
documentation = [ "man:tang(8)" ];
path = [ pkgs.jose ];
serviceConfig = {
Type = "oneshot";
StandardError = "journal";
ExecStart = "${pkgs.tang}/libexec/tangd-keygen /var/db/tang";
};
};
systemd.services."tangd@" = {
description = "Tang Server";
documentation = [ "man:tang(8)" ];
path = [ pkgs.jose ];
serviceConfig = {
StandardInput = "socket";
StandardOutput = "socket";
StandardError = "journal";
ExecStart = "${pkgs.tang}/libexec/tangd /var/cache/tang";
};
};
systemd.sockets.tangd = {
description = "Tang Server socket";
documentation = [ "man:tang(8)" ];
requires = [
"tangd-keygen.service"
"tangd-update.service"
"tangd-update.path"
];
after = [
"tangd-keygen.service"
"tangd-update.service"
];
wantedBy = [ "multi-user.target" ];
socketConfig = {
ListenStream = 8000;
Accept = true;
};
};
# users.groups.tang = {};
# users.users.tang = {
# isSystemUser = true;
# group = "tang";
# home = "/var/db/tang";
# createHome = true;
# description = "Tang system user";
# };
}

View File

@@ -1,13 +0,0 @@
{ config, pkgs, ... }:
let
tuxedo = import (builtins.fetchTarball "https://github.com/blitz/tuxedo-nixos/archive/master.tar.gz");
in {
# ...
imports = [
tuxedo.module
];
hardware.tuxedo-control-center.enable = true;
}

View File

@@ -1,19 +0,0 @@
{ pkgs, ... }:
{
services.resolved.enable = true;
services.openvpn.servers = {
epicenterWorks = {
config = ''
config /etc/nixos/modules/vpn/epicenter.works/vpn.conf
script-security 2
up ${pkgs.update-systemd-resolved}/libexec/openvpn/update-systemd-resolved
up-restart
down ${pkgs.update-systemd-resolved}/libexec/openvpn/update-systemd-resolved
down-pre
'';
};
};
}

View File

@@ -1,40 +0,0 @@
{ pkgs, ... }:
{
networking.firewall = {
allowedUDPPorts = [ 51820 ]; # Clients and peers can use the same port, see listenport
};
# Enable WireGuard
networking.wireguard.interfaces = {
# "wg0" is the network interface name. You can name the interface arbitrarily.
wg0 = {
# Determines the IP address and subnet of the client's end of the tunnel interface.
ips = [ "10.50.60.6/24" ];
listenPort = 51820; # to match firewall allowedUDPPorts (without this wg uses random port numbers)
privateKeyFile = "/run/secrets/wg_private_key";
postSetup = ''printf "search epicenter.works\nnameserver 10.25.0.10" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0'';
postShutdown = "${pkgs.openresolv}/bin/resolvconf -d wg0";
peers = [
# For a client configuration, one peer entry for the server will suffice.
{
# Public key of the server (not a file path).
publicKey = "T7jPGSapSudtKyWwi2nu+2hjjse96I4U3lccRHZWd2s=";
presharedKeyFile = "/run/secrets/wg_preshared_key";
allowedIPs = [ "10.50.60.0/24" "10.25.0.0/24" ];
# Set this to the server IP and port.
endpoint = "5.9.131.17:51821"; # ToDo: route to endpoint not automatically configured https://wiki.archlinux.org/index.php/WireGuard#Loop_routing https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577
# Send keepalives every 25 seconds. Important to keep NAT tables alive.
persistentKeepalive = 25;
}
];
};
};
}

View File

@@ -1,14 +0,0 @@
dev tun
persist-tun
persist-key
cipher AES-128-GCM
auth RSA-SHA256
client
resolv-retry infinite
remote vpn.epicenter.works 1195 udp
lport 0
verify-x509-name "C=AT, ST=Vienna, L=Vienna, O=epicenter_works, emailAddress=team@epicenter.works, CN=epicenter.works VPN Server" subject
remote-cert-tls server
ca /run/secrets/epicenter_vpn_ca
cert /run/secrets/epicenter_vpn_cert
key /run/secrets/epicenter_vpn_key

View File

@@ -1,135 +0,0 @@
{ pkgs, lib, config, ... }:
let
domain = "cloonar.dev";
dataDir = "/var/www/${domain}";
in {
systemd.services."phpfpm-${domain}".serviceConfig.ProtectHome = lib.mkForce false;
services.phpfpm.pools."${domain}" = {
user = domain;
settings = {
"listen.owner" = config.services.nginx.user;
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = true;
"catch_workers_output" = true;
"access.log" = "/var/log/$pool.access.log";
};
phpPackage = pkgs.php81;
phpEnv."PATH" = lib.makeBinPath [ pkgs.php81 ];
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
root = "${dataDir}";
locations."/favicon.ico".extraConfig = ''
log_not_found off;
access_log off;
'';
# TYPO3 - Rule for versioned static files, configured through:
# - $GLOBALS['TYPO3_CONF_VARS']['BE']['versionNumberInFilename']
# - $GLOBALS['TYPO3_CONF_VARS']['FE']['versionNumberInFilename']
extraConfig = ''
if (!-e $request_filename) {
rewrite ^/(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ /$1.$3 last;
}
'';
# TYPO3 - Block access to composer files
locations."~* composer\.(?:json|lock)".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to flexform files
locations."~* flexform[^.]*\.xml".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to language files
locations."~* locallang[^.]*\.(?:xml|xlf)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to static typoscript files
locations."~* ext_conf_template\.txt|ext_typoscript_constants\.txt|ext_typoscript_setup\.txt".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to miscellaneous protected files
locations."~* /.*\.(?:bak|co?nf|cfg|ya?ml|ts|typoscript|tsconfig|dist|fla|in[ci]|log|sh|sql|sqlite)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to recycler and temporary directories
locations."~ _(?:recycler|temp)_/".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to configuration files stored in fileadmin
locations."~ fileadmin/(?:templates)/.*\.(?:txt|ts|typoscript)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to libraries, source and temporary compiled data
locations."~ ^(?:vendor|typo3_src|typo3temp/var)".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to protected extension directories
locations."~ (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|Resources/Private|Tests?|Documentation|docs?)/".extraConfig = ''
deny all;
'';
locations."/".extraConfig = ''
index index.php index.html;
try_files $uri $uri/ /index.php$is_args$args;
'';
# TYPO3 Backend URLs
locations."/typo3".extraConfig = ''
rewrite ^ /typo3/;
'';
locations."/typo3/".extraConfig = ''
try_files $uri /typo3/index.php$is_args$args;
'';
locations."~ [^/]\.php(/|$)".extraConfig = ''
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 16k;
fastcgi_connect_timeout 240s;
fastcgi_read_timeout 240s;
fastcgi_send_timeout 240s;
fastcgi_pass unix:${config.services.phpfpm.pools."${domain}".socket};
fastcgi_index index.php;
'';
};
users.users."${domain}" = {
isSystemUser = true;
createHome = true;
home = dataDir;
homeMode= "770";
#home = "/home/${domain}";
group = "nginx";
};
users.groups.${domain} = {};
}

View File

@@ -1,56 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
./cloonar.dev.nix
./diabetes-austria.cloonar.dev.nix
];
environment.systemPackages = with pkgs; [
imagemagick
ghostscript
];
systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
commonHttpConfig = ''
# Add HSTS header with preloading to HTTPS requests.
# Adding this header to HTTP requests is discouraged
map $scheme $hsts_header {
https "max-age=31536000; includeSubdomains; preload";
}
add_header Strict-Transport-Security $hsts_header;
# Enable CSP for your services.
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
# Minimize information leaked to other domains
add_header 'Referrer-Policy' 'origin-when-cross-origin';
# Disable embedding as a frame
add_header X-Frame-Options DENY;
# Prevent injection of code in other mime types (XSS Attacks)
add_header X-Content-Type-Options nosniff;
# Enable XSS protection of the browser.
# May be unnecessary when CSP is configured properly (see above)
add_header X-XSS-Protection "1; mode=block";
# This might create errors
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
'';
};
}

View File

@@ -1,135 +0,0 @@
{ pkgs, lib, config, ... }:
let
domain = "diabetes-austria.cloonar.dev";
dataDir = "/var/www/${domain}";
in {
systemd.services."phpfpm-${domain}".serviceConfig.ProtectHome = lib.mkForce false;
services.phpfpm.pools."${domain}" = {
user = domain;
settings = {
"listen.owner" = config.services.nginx.user;
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = true;
"catch_workers_output" = true;
"access.log" = "/var/log/$pool.access.log";
};
phpPackage = pkgs.php81;
phpEnv."PATH" = lib.makeBinPath [ pkgs.php81 ];
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
root = "${dataDir}";
locations."/favicon.ico".extraConfig = ''
log_not_found off;
access_log off;
'';
# TYPO3 - Rule for versioned static files, configured through:
# - $GLOBALS['TYPO3_CONF_VARS']['BE']['versionNumberInFilename']
# - $GLOBALS['TYPO3_CONF_VARS']['FE']['versionNumberInFilename']
extraConfig = ''
if (!-e $request_filename) {
rewrite ^/(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ /$1.$3 last;
}
'';
# TYPO3 - Block access to composer files
locations."~* composer\.(?:json|lock)".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to flexform files
locations."~* flexform[^.]*\.xml".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to language files
locations."~* locallang[^.]*\.(?:xml|xlf)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to static typoscript files
locations."~* ext_conf_template\.txt|ext_typoscript_constants\.txt|ext_typoscript_setup\.txt".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to miscellaneous protected files
locations."~* /.*\.(?:bak|co?nf|cfg|ya?ml|ts|typoscript|tsconfig|dist|fla|in[ci]|log|sh|sql|sqlite)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to recycler and temporary directories
locations."~ _(?:recycler|temp)_/".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to configuration files stored in fileadmin
locations."~ fileadmin/(?:templates)/.*\.(?:txt|ts|typoscript)$".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to libraries, source and temporary compiled data
locations."~ ^(?:vendor|typo3_src|typo3temp/var)".extraConfig = ''
deny all;
'';
# TYPO3 - Block access to protected extension directories
locations."~ (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|Resources/Private|Tests?|Documentation|docs?)/".extraConfig = ''
deny all;
'';
locations."/".extraConfig = ''
index index.php index.html;
try_files $uri $uri/ /index.php$is_args$args;
'';
# TYPO3 Backend URLs
locations."/typo3".extraConfig = ''
rewrite ^ /typo3/;
'';
locations."/typo3/".extraConfig = ''
try_files $uri /typo3/index.php$is_args$args;
'';
locations."~ [^/]\.php(/|$)".extraConfig = ''
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 16k;
fastcgi_connect_timeout 240s;
fastcgi_read_timeout 240s;
fastcgi_send_timeout 240s;
fastcgi_pass unix:${config.services.phpfpm.pools."${domain}".socket};
fastcgi_index index.php;
'';
};
users.users."${domain}" = {
isSystemUser = true;
createHome = true;
home = dataDir;
homeMode= "770";
#home = "/home/${domain}";
group = "nginx";
};
users.groups.${domain} = {};
}