mob next [ci-skip] [ci skip] [skip ci]

lastFile:modules/nixos/think-gtcm.nix
This commit is contained in:
2025-11-24 13:40:14 +00:00
parent 52df526ac5
commit 3e95cd0310

View File

@@ -11,14 +11,33 @@ let
defaultUser = "gtcm";
defaultGroup = "gtcm";
env-nonfile-values = lib.attrsets.filterAttrs (n: v: !lib.strings.hasSuffix "_FILE" n) cfg.settings;
think-gtcm-maintenance = pkgs.writeShellScript "think-gtcm-maintenance.sh" ''
set -a
${lib.strings.toShellVars env-nonfile-values}
set +a
php = pkgs.php83;
artisan = pkgs.writeShellScript "gtcm" ''
#! #{pkgs.runtimeShell}
cd ${think-gtcm}
sudo() {
if [[ "$USER" != ${cfg.user} ]]; then
exec /run/wrappers/bin/sudo -u ${cfg.user} "$@"
else
exec "$@"
fi
}
sudo ${php} artisan "$@"
'';
artisan-be = pkgs.writeShellScript "gtcm-be" ''
#! #{pkgs.runtimeShell}
cd ${think-gtcm}
sudo() {
if [[ "$USER" != ${cfg.user} ]]; then
exec /run/wrappers/bin/sudo -u ${cfg.user} "$@"
else
exec "$@"
fi
}
sudo ${php} artisan "$@"
'';
in
{
options.services.think-greaterchiangmai = {
@@ -64,64 +83,54 @@ in
};
settings = lib.mkOption {
lib.type =
with lib.types;
attrsOf (
nullOr (
either
(oneOf [
bool
int
port
path
str
])
(submodule {
options = {
_secret = mkOption {
type = nullOr str;
description = ''
The path to a file containing the value the
option should be set to in the final
configuration file.
'';
};
};
})
)
);
default = { };
description = ''
Options for settings environment variables
'';
example = lib.literalExpression ''
{
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_NAME = "Laravel";
APP_ENV = "local";
APP_KEY = "key";
APP_DEBUG = true;
APP_URL = "http://localhost";
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
LOG_CHANNEL = "stack";
LOG_DEPRECATIONS_CHANNEL = "null";
LOG_LEVEL = "debug";
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="''${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
DB_CONNECTION = "mysql";
DB_HOST = "127.0.0.1";
DB_PORT = "3306";
DB_DATABASE = "laravel";
DB_USERNAME = "root";
DB_PASSWORD = "";
}
'';
type = lib.types.submodule {
@@ -201,11 +210,12 @@ in
};
users.groups.${cfg.group} = { };
services.phpfpm.pools.think-greaterchiangmai = {
services.phpfpm.pools.think-gtcm = {
inherit (cfg) user group;
phpPackage = php;
settings = {
"listen.owner" = config.services.nginx.user;
"listen.group" = config.services.nginx.group;
"listen.owner" = cfg.user;
"listen.group" = cfg.group;
"listen.mode" = "0600";
"pm" = lib.mkDefault "dynamic";
"pm.max_children" = lib.mkDefault 10;
@@ -222,33 +232,117 @@ in
systemd.services.think-gtcm-setup = {
description = "think.greaterchiangmai installation";
requiredBy = [ "phpfpm-think-greaterchiangmai.service" ];
before = [ "phpfpm-think-greaterchiangmai.service" ];
requiredBy = [ "phpfpm-think-gtcm.service" ];
before = [ "phpfpm-think-gtcm.service" ];
requires = [ "mysql.service" ];
after = [ "mysql.service" ];
path = [ config.services.phpfpm.phpPackage ];
serviceConfig = {
type = "oneshot";
RemainAfterExit = true;
User = cfg.user;
UMask = 77;
WorkingDirectory = "${agorakit}";
RuntimeDirectory = "agorakit/cache";
WorkingDirectory = "${think-gtcm}";
RuntimeDirectory = "think-gtcm/cache";
RuntimeDirectoryMode = 700;
ExecStart = think-gtcm-maintenance;
};
path = [ pkgs.replace-secret ];
script =
let
isSecret = v: lib.isAttrs v && v ? _secret && lib.isString v._secret;
gtcmEnvVars = lib.generators.toKeyValue {
mkKeyValue = lib.flip lib.generators.mkKeyValueDefault "=" {
mkValueString =
v:
with builtins;
if isInt v then
toString v
else if isString v then
v
else if true == v then
"true"
else if false == v then
"false"
else if isSecret v then
hashString "sha256" v._secret
else
throw "unsupported type ${typeOf v}: ${(lib.generators.toPretty { }) v}";
};
};
secretPaths = lib.mapAttrsToList (_: v: v._secret) (lib.filterAttrs (_: isSecret) cfg.config);
mkSecretReplacement = file: ''
replace-secret ${
lib.escapeShellArgs [
(builtins.hashString "sha256" file)
file
"${cfg.dataDir}/.env"
]
}
'';
secretReplacements = lib.concatMapStrings mkSecretReplacement secretPaths;
filteredConfig = lib.converge (lib.filterAttrsRecursive (
_: v:
!lib.elem v [
{ }
null
]
)) cfg.settings;
gtcmEnv = pkgs.writeText "gtcm.env" (gtcmEnvVars filteredConfig);
in
''
# error handling
set -euo pipefail
# create .env file
install -T -m 0600 -o ${cfg.user} ${gtcmEnv} "${cfg.dataDir}/.env"
${secretReplacements}
if ! grep 'APP_KEY=base64:' "${cfg.dataDir}/.env" >/dev/null; then
sed -i 's/APP_KEY=/APP_KEY=base64:/' "${cfg.dataDir}/.env"
fi
# migrate & seed db
${php} artisan key:generate --force
${php} artisan migrate --force
${php} artisan config:cache
'';
};
systemd.tmpfiles.rules = [
"d ${cfg.dataDir} 0710 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/public 0750 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/public/uploads 0750 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/app 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/fonts 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/framework 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/framework/cache 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/framework/sessions 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/framework/views 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/logs 0700 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/storage/uploads 0700 ${cfg.user} ${cfg.group} - -"
];
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedBrotliSettings = true;
recommendedProxySettings = true;
virtualHosts."${cfg.domain}" = {
root = "${cfg.package}/share/php/think-gtcm/public";
locations."~ \\.php$".extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.think-greaterchiangmai.socket};
fastcgi_index index.php;
'';
extraConfig = ''
index index.php;
locations = {
"/" = {
index = "index.php";
tryFiles = "$uri $uri/ /index.php?$query_string";
};
"~ \\.php$".extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools."think-gtcm".socket};
'';
"~ \\.(js|css|gif|png|ico|jpg|jpeg)$" = {
extraConfig = "expires 365d;";
};
};
};
# virtualHosts."${cfg.backendDomain}" = {
# root = "${cfg.packageBackend}/share/php/think-backend-gtcm/public";