move modules to web host
This commit is contained in:
319
hosts/web-01.cloonar.com/modules/web/stack.nix
Normal file
319
hosts/web-01.cloonar.com/modules/web/stack.nix
Normal file
@@ -0,0 +1,319 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.webstack;
|
||||
|
||||
instanceOpts = { name, ... }:
|
||||
{
|
||||
options = {
|
||||
user = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
User of the typo3 instance. Defaults to attribute name in instances.
|
||||
'';
|
||||
example = "example.org";
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Domain of the typo3 instance. Defaults to attribute name in instances.
|
||||
'';
|
||||
example = "example.org";
|
||||
};
|
||||
|
||||
domainAliases = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "www.example.org" "example.org" ];
|
||||
description = lib.mdDoc ''
|
||||
Additional domains served by this typo3 instance.
|
||||
'';
|
||||
};
|
||||
|
||||
phpPackage = mkOption {
|
||||
type = types.package;
|
||||
example = literalExpression "pkgs.php";
|
||||
description = lib.mdDoc ''
|
||||
Which PHP package to use in this typo3 instance.
|
||||
'';
|
||||
};
|
||||
|
||||
enableMysql = mkEnableOption (lib.mdDoc "MySQL Database");
|
||||
enableDefaultLocations = mkEnableOption (lib.mdDoc "Create default nginx location directives") // { default = true; };
|
||||
|
||||
authorizedKeys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Authorized keys for the typo3 instance ssh user.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^/(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ /$1.$3 last;
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
These lines go to the end of the vhost verbatim.
|
||||
'';
|
||||
};
|
||||
|
||||
locations = mkOption {
|
||||
type = types.attrsOf (types.submodule (import <nixpkgs/nixos/modules/services/web-servers/nginx/location-options.nix> {
|
||||
inherit lib config;
|
||||
}));
|
||||
default = {};
|
||||
example = literalExpression ''
|
||||
{
|
||||
"/" = {
|
||||
proxyPass = "http://localhost:3000";
|
||||
};
|
||||
};
|
||||
'';
|
||||
description = lib.mdDoc "Declarative location config";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
options.services.webstack = {
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/www";
|
||||
description = lib.mdDoc ''
|
||||
The data directory for MySQL.
|
||||
|
||||
::: {.note}
|
||||
If left as the default value of `/var/www` this directory will automatically be created before the web
|
||||
server starts, otherwise you are responsible for ensuring the directory exists with appropriate ownership and permissions.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
instances = mkOption {
|
||||
type = types.attrsOf (types.submodule instanceOpts);
|
||||
default = {};
|
||||
description = lib.mdDoc "Create vhosts for typo3";
|
||||
example = literalExpression ''
|
||||
{
|
||||
"typo3.example.com" = {
|
||||
domain = "example.com";
|
||||
domainAliases = [ "www.example.com" ];
|
||||
phpPackage = pkgs.php81;
|
||||
authorizedKeys = [
|
||||
"ssh-rsa AZA=="
|
||||
];
|
||||
};
|
||||
};
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
systemd.services = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
in
|
||||
nameValuePair "phpfpm-${domain}" {
|
||||
serviceConfig = {
|
||||
ProtectHome = lib.mkForce "tmpfs";
|
||||
BindPaths = "BindPaths=/var/www/${domain}:/var/www/${domain}";
|
||||
};
|
||||
}
|
||||
) cfg.instances;
|
||||
|
||||
services.phpfpm.pools = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair domain {
|
||||
user = user;
|
||||
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]" = "syslog";
|
||||
"php_admin_value[max_execution_time]" = 240;
|
||||
"php_admin_value[max_input_vars]" = 1500;
|
||||
"access.log" = "/var/log/$pool.access.log";
|
||||
};
|
||||
phpPackage = instanceOpts.phpPackage;
|
||||
phpEnv."PATH" = pkgs.lib.makeBinPath [ instanceOpts.phpPackage ];
|
||||
}
|
||||
) cfg.instances;
|
||||
|
||||
};
|
||||
|
||||
|
||||
config.services.nginx.virtualHosts = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair domain {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = null;
|
||||
root = cfg.dataDir + "/" + domain + "/public";
|
||||
|
||||
locations = lib.mkMerge [
|
||||
instanceOpts.locations
|
||||
(mkIf instanceOpts.enableDefaultLocations {
|
||||
"/favicon.ico".extraConfig = ''
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
'';
|
||||
|
||||
# Cache.appcache, your document html and data
|
||||
"~* \\.(?:manifest|appcache|html?|xml|json)$".extraConfig = ''
|
||||
expires -1;
|
||||
# access_log logs/static.log; # I don't usually include a static log
|
||||
'';
|
||||
|
||||
"~* \\.(jpe?g|png)$".extraConfig = ''
|
||||
set $red Z;
|
||||
|
||||
if ($http_accept ~* "webp") {
|
||||
set $red A;
|
||||
}
|
||||
|
||||
if (-f $document_root/webp/$request_uri.webp) {
|
||||
set $red "''${red}B";
|
||||
}
|
||||
|
||||
if ($red = "AB") {
|
||||
add_header Vary Accept;
|
||||
rewrite ^ /webp/$request_uri.webp;
|
||||
}
|
||||
'';
|
||||
|
||||
# Cache Media: images, icons, video, audio, HTC
|
||||
"~* \\.(?:jpg|jpeg|gif|png|webp|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff2)$".extraConfig = ''
|
||||
expires 1y;
|
||||
access_log off;
|
||||
add_header Cache-Control "public";
|
||||
'';
|
||||
|
||||
# Feed
|
||||
"~* \\.(?:rss|atom)$".extraConfig = ''
|
||||
expires 1h;
|
||||
add_header Cache-Control "public";
|
||||
'';
|
||||
|
||||
# Cache CSS, Javascript, Images, Icons, Video, Audio, HTC, Fonts
|
||||
"~* \\.(?:css|js|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff2)$".extraConfig = ''
|
||||
expires 1y;
|
||||
access_log off;
|
||||
add_header Cache-Control "public";
|
||||
'';
|
||||
|
||||
"/".extraConfig = ''
|
||||
index index.php index.html;
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
'';
|
||||
})
|
||||
{
|
||||
"~ [^/]\\.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;
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
extraConfig = instanceOpts.extraConfig;
|
||||
|
||||
|
||||
# locations = mapAttrs' (location: locationOpts:
|
||||
# nameValuePair location locationOpts) instanceOpts.locations;
|
||||
|
||||
}
|
||||
) cfg.instances;
|
||||
|
||||
config.users.users = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair user {
|
||||
isNormalUser = true;
|
||||
createHome = true;
|
||||
home = "/var/www/" + domain;
|
||||
homeMode= "770";
|
||||
group = config.services.nginx.group;
|
||||
openssh.authorizedKeys.keys = instanceOpts.authorizedKeys;
|
||||
}
|
||||
) cfg.instances;
|
||||
config.users.groups = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in nameValuePair user {}) cfg.instances;
|
||||
|
||||
config.services.mysql.ensureUsers = mapAttrsToList (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
mkIf instanceOpts.enableMysql {
|
||||
name = user;
|
||||
ensurePermissions = {
|
||||
"${user}.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}) cfg.instances;
|
||||
|
||||
config.services.mysql.ensureDatabases = mapAttrsToList (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
mkIf instanceOpts.enableMysql user
|
||||
) cfg.instances;
|
||||
config.services.mysqlBackup.databases = mapAttrsToList (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
mkIf instanceOpts.enableMysql user
|
||||
) cfg.instances;
|
||||
}
|
||||
|
||||
445
hosts/web-01.cloonar.com/modules/web/typo3.nix
Normal file
445
hosts/web-01.cloonar.com/modules/web/typo3.nix
Normal file
@@ -0,0 +1,445 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.typo3;
|
||||
|
||||
instanceOpts = { name, ... }:
|
||||
{
|
||||
options = {
|
||||
user = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
User of the typo3 instance. Defaults to attribute name in instances.
|
||||
'';
|
||||
example = "example.org";
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Domain of the typo3 instance. Defaults to attribute name in instances.
|
||||
'';
|
||||
example = "example.org";
|
||||
};
|
||||
|
||||
domainAliases = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "www.example.org" "example.org" ];
|
||||
description = lib.mdDoc ''
|
||||
Additional domains served by this typo3 instance.
|
||||
'';
|
||||
};
|
||||
|
||||
phpPackage = mkOption {
|
||||
type = types.package;
|
||||
example = literalExpression "pkgs.php";
|
||||
description = lib.mdDoc ''
|
||||
Which PHP package to use in this typo3 instance.
|
||||
'';
|
||||
};
|
||||
|
||||
authorizedKeys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Authorized keys for the typo3 instance ssh user.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
options.services.typo3 = {
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/www";
|
||||
description = lib.mdDoc ''
|
||||
The data directory for MySQL.
|
||||
|
||||
::: {.note}
|
||||
If left as the default value of `/var/www` this directory will automatically be created before the web
|
||||
server starts, otherwise you are responsible for ensuring the directory exists with appropriate ownership and permissions.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
instances = mkOption {
|
||||
type = types.attrsOf (types.submodule instanceOpts);
|
||||
default = {};
|
||||
description = lib.mdDoc "Create vhosts for typo3";
|
||||
example = literalExpression ''
|
||||
{
|
||||
"typo3.example.com" = {
|
||||
domain = "example.com";
|
||||
domainAliases = [ "www.example.com" ];
|
||||
phpPackage = pkgs.php82;
|
||||
authorizedKeys = [
|
||||
"ssh-rsa AZA=="
|
||||
];
|
||||
};
|
||||
};
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
# systemd.services = mapAttrs' (instance: instanceOpts:
|
||||
# let
|
||||
# domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
# in
|
||||
# nameValuePair "phpfpm-${domain}" {
|
||||
# serviceConfig = {
|
||||
# ProtectHome = lib.mkForce "tmpfs";
|
||||
# BindPaths = "BindPaths=/var/www/${domain}:/var/www/${domain}";
|
||||
# };
|
||||
# }
|
||||
# ) cfg.instances;
|
||||
|
||||
systemd.timers = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair ("typo3-cron-" + domain) {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "05:00";
|
||||
Unit = "typo3-cron-" + domain + ".service";
|
||||
};
|
||||
}
|
||||
) cfg.instances;
|
||||
systemd.services = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair ("typo3-cron-" + domain) {
|
||||
script = ''
|
||||
set -eu
|
||||
${instanceOpts.phpPackage}/bin/php /var/www/${domain}/.Build/bin/typo3 scheduler:run
|
||||
${instanceOpts.phpPackage}/bin/php /var/www/${domain}/.Build/bin/typo3 ke_search:indexing
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = user;
|
||||
};
|
||||
}
|
||||
) cfg.instances;
|
||||
|
||||
services.phpfpm.pools = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair domain {
|
||||
user = user;
|
||||
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]" = "syslog";
|
||||
"php_admin_value[max_execution_time]" = 240;
|
||||
"php_admin_value[max_input_vars]" = 1500;
|
||||
"php_admin_value[upload_max_filesize]" = "256M";
|
||||
"php_admin_value[post_max_size]" = "256M";
|
||||
"access.log" = "/var/log/$pool.access.log";
|
||||
};
|
||||
phpOptions = ''
|
||||
opcache.enable=1
|
||||
opcache.memory_consumption=128
|
||||
opcache.validate_timestamps=0
|
||||
opcache.revalidate_path=0
|
||||
'';
|
||||
phpPackage = instanceOpts.phpPackage;
|
||||
phpEnv."PATH" = pkgs.lib.makeBinPath [ instanceOpts.phpPackage ];
|
||||
}
|
||||
) cfg.instances;
|
||||
|
||||
};
|
||||
|
||||
|
||||
config.services.nginx.virtualHosts = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair domain {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = null;
|
||||
root = cfg.dataDir + "/" + domain + "/public";
|
||||
serverAliases = instanceOpts.domainAliases;
|
||||
|
||||
extraConfig = ''
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^/(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ /$1.$3 last;
|
||||
}
|
||||
|
||||
# Virtual endpoint created by nginx to forward auth requests.
|
||||
location /authelia {
|
||||
internal;
|
||||
set $upstream_authelia http://127.0.0.1:9091/api/verify;
|
||||
proxy_pass_request_body off;
|
||||
proxy_pass $upstream_authelia;
|
||||
proxy_set_header Content-Length "";
|
||||
|
||||
# Timeout if the real server is dead
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
||||
|
||||
# [REQUIRED] Needed by Authelia to check authorizations of the resource.
|
||||
# Provide either X-Original-URL and X-Forwarded-Proto or
|
||||
# X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Uri or both.
|
||||
# Those headers will be used by Authelia to deduce the target url of the user.
|
||||
# Basic Proxy Config
|
||||
client_body_buffer_size 128k;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 4 32k;
|
||||
|
||||
# Advanced Proxy Config
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 240;
|
||||
proxy_send_timeout 240;
|
||||
proxy_connect_timeout 240;
|
||||
}
|
||||
'';
|
||||
|
||||
locations."/typo3/login" = {
|
||||
extraConfig = ''
|
||||
# Basic Authelia Config
|
||||
# Send a subsequent request to Authelia to verify if the user is authenticated
|
||||
# and has the right permissions to access the resource.
|
||||
auth_request /authelia;
|
||||
# Set the `target_url` variable based on the request. It will be used to build the portal
|
||||
# URL with the correct redirection parameter.
|
||||
auth_request_set $target_url $scheme://$http_host$request_uri;
|
||||
# Set the X-Forwarded-User and X-Forwarded-Groups with the headers
|
||||
# returned by Authelia for the backends which can consume them.
|
||||
# This is not safe, as the backend must make sure that they come from the
|
||||
# proxy. In the future, it's gonna be safe to just use OAuth.
|
||||
auth_request_set $user $upstream_http_remote_user;
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
auth_request_set $name $upstream_http_remote_name;
|
||||
auth_request_set $email $upstream_http_remote_email;
|
||||
proxy_set_header Remote-User $user;
|
||||
proxy_set_header Remote-Groups $groups;
|
||||
proxy_set_header Remote-Name $name;
|
||||
proxy_set_header Remote-Email $email;
|
||||
# If Authelia returns 401, then nginx redirects the user to the login portal.
|
||||
# If it returns 200, then the request pass through to the backend.
|
||||
# For other type of errors, nginx will handle them as usual.
|
||||
error_page 401 =302 https://auth.cloonar.com/?rd=$target_url;
|
||||
|
||||
fastcgi_param REMOTE_USER $user;
|
||||
|
||||
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_param SCRIPT_FILENAME ${cfg.dataDir}/${domain}/public/typo3/index.php;
|
||||
'';
|
||||
};
|
||||
|
||||
locations."/favicon.ico".extraConfig = ''
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
'';
|
||||
|
||||
# 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;
|
||||
'';
|
||||
# locations."~* /.*\.(?:bak|cfg|co?nf|ya?ml|ts)$".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;
|
||||
'';
|
||||
|
||||
# Cache.appcache, your document html and data
|
||||
locations."~* \\.(?:manifest|appcache|html?|xml|json)$".extraConfig = ''
|
||||
expires -1;
|
||||
# access_log logs/static.log; # I don't usually include a static log
|
||||
'';
|
||||
|
||||
# Cache Media: images, icons, video, audio, HTC
|
||||
locations."~* \\.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff2)$".extraConfig = ''
|
||||
expires 1y;
|
||||
access_log off;
|
||||
add_header Cache-Control "public";
|
||||
'';
|
||||
|
||||
# Feed
|
||||
locations."~* \\.(?:rss|atom)$".extraConfig = ''
|
||||
expires 1h;
|
||||
add_header Cache-Control "public";
|
||||
'';
|
||||
|
||||
# Cache CSS, Javascript, Images, Icons, Video, Audio, HTC, Fonts
|
||||
locations."~* \\.(?:css|js|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff2)$".extraConfig = ''
|
||||
expires 1y;
|
||||
access_log off;
|
||||
add_header Cache-Control "public";
|
||||
'';
|
||||
|
||||
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.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;
|
||||
'';
|
||||
}
|
||||
) cfg.instances;
|
||||
|
||||
config.users.users = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
nameValuePair user {
|
||||
isNormalUser = true;
|
||||
createHome = true;
|
||||
home = "/var/www/" + domain;
|
||||
homeMode= "770";
|
||||
group = config.services.nginx.group;
|
||||
openssh.authorizedKeys.keys = instanceOpts.authorizedKeys;
|
||||
}
|
||||
) cfg.instances;
|
||||
config.users.groups = mapAttrs' (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in nameValuePair user {}) cfg.instances;
|
||||
|
||||
config.services.mysql.ensureUsers = mapAttrsToList (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
{
|
||||
name = user;
|
||||
ensurePermissions = {
|
||||
"${user}.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}) cfg.instances;
|
||||
|
||||
config.services.mysql.ensureDatabases = mapAttrsToList (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
user
|
||||
) cfg.instances;
|
||||
config.services.mysqlBackup.databases = mapAttrsToList (instance: instanceOpts:
|
||||
let
|
||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||
user = if instanceOpts.user != null
|
||||
then instanceOps.user
|
||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||
in
|
||||
user
|
||||
) cfg.instances;
|
||||
}
|
||||
Reference in New Issue
Block a user