modules: add initial sketch of wp for nginx
This commit is contained in:
parent
2fa0b052f6
commit
a37d79c31c
12 changed files with 453 additions and 0 deletions
|
@ -2,4 +2,5 @@
|
|||
acme-dns = ./servers/acme-dns.nix;
|
||||
drone-server = ./servers/drone.nix;
|
||||
drone-exec-runner = ./servers/drone-exec-runner.nix;
|
||||
wordpress = ./web-apps/wordpress;
|
||||
}
|
||||
|
|
128
modules/web-apps/wordpress/app.nix
Normal file
128
modules/web-apps/wordpress/app.nix
Normal file
|
@ -0,0 +1,128 @@
|
|||
with import ./utils.nix;
|
||||
let
|
||||
writeableDefault = {
|
||||
appPaths = []; # list of paths in the app to make writeable
|
||||
pkgPath = "_writeable"; # path to create in read-only package that stores original content of writeable paths
|
||||
sysPath = required "writeable.sysPath" ''system path to store writeable data (e.g. "/var/lib/phpfpm/my-app")'';
|
||||
owner = required "writeable.owner" "user which owns the writeable files";
|
||||
};
|
||||
in
|
||||
{ callPackage
|
||||
, lib
|
||||
, runCommand
|
||||
, writeScript
|
||||
, writeText
|
||||
|
||||
, appConfig
|
||||
, writeable ? writeableDefault
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
# Merge the given writeable settings with the defaults.
|
||||
writeable_ = writeableDefault // writeable;
|
||||
|
||||
# We only care about writeble paths if the app is mostly frozen.
|
||||
writeablePaths = lib.optionals appConfig.freezeWordPress (
|
||||
["wp-content/uploads"]
|
||||
++ lib.optional (!appConfig.freezePlugins) "wp-content/plugins"
|
||||
++ lib.optional (!appConfig.freezeThemes) "wp-content/themes"
|
||||
++ writeable_.appPaths
|
||||
);
|
||||
|
||||
wordpress = callPackage appConfig.wordpress {};
|
||||
plugins = callPackage appConfig.plugins {};
|
||||
themes = callPackage appConfig.themes {};
|
||||
|
||||
# The wp-config.php file.
|
||||
wpConfigFile = writeText "wp-config.php" appConfig.wpConfig.rendered;
|
||||
|
||||
# Generates a list of paths in bash that can be looped over.
|
||||
listOfPaths = lib.concatMapStringsSep " " (x: "'${x}'");
|
||||
|
||||
# Generates the bash command to install a path from source to destination.
|
||||
# If the install is `frozen`, then we simply symlink, otherwise we copy.
|
||||
installPath = isFrozen: from: to:
|
||||
(if isFrozen then "ln -s" else "cp -r") + " " + ''"${from}" "${to}"'';
|
||||
|
||||
# The build script for the app.
|
||||
# This will install WordPress, the wp-config, plugins, and themes.
|
||||
# If any writeble paths were configured, this script will copy them to a another folder in the
|
||||
# package and set up symlinks in their place the given writeable path on the system.
|
||||
buildPackageAt = out: ''
|
||||
mkdir -p $(dirname "${out}") # Make parent directory.
|
||||
|
||||
cp -r "${wordpress}" "${out}"
|
||||
chmod -R +w "${out}"
|
||||
|
||||
${installPath appConfig.freezeWordPress wpConfigFile "${out}/wp-config.php"}
|
||||
|
||||
# Install themes.
|
||||
rm -r "${out}/wp-content/themes"/* # remove bundled themes
|
||||
${lib.concatMapStringsSep "\n" (x: installPath appConfig.freezeThemes x "${out}/wp-content/themes/${x.name}") themes}
|
||||
|
||||
# Install plugins.
|
||||
rm -r "${out}/wp-content/plugins"/* # remove bundled plugins
|
||||
${lib.concatMapStringsSep "\n" (x: installPath appConfig.freezePlugins x "${out}/wp-content/plugins/${x.name}") plugins}
|
||||
|
||||
# TODO: Support translations.
|
||||
|
||||
${lib.optionalString (writeablePaths != []) ''
|
||||
# Make symlinks to writeable directories.
|
||||
writeable_orig_dir="${out}/${writeable_.pkgPath}"
|
||||
mkdir -p "$writeable_orig_dir"
|
||||
|
||||
for thing in ${listOfPaths writeablePaths}; do
|
||||
original_thing="$writeable_orig_dir/$thing"
|
||||
parent=$(dirname "$original_thing")
|
||||
mkdir -p "$parent"
|
||||
|
||||
# Move any existing data to the frozen writeable dir or create empty directory there.
|
||||
mv "${out}/$thing" "$parent" || mkdir -p "$original_thing"
|
||||
|
||||
ln -s "${writeable_.sysPath}/$thing" "${out}/$thing"
|
||||
done
|
||||
''}
|
||||
'';
|
||||
|
||||
# Copy the original writeable contents of the package to a writeable dir.
|
||||
initWriteablePathsFor = package: ''
|
||||
mkdir -p "$out"
|
||||
writeable_orig_dir="${package}/${writeable_.pkgPath}"
|
||||
for thing in $( ls "$writeable_orig_dir" ); do
|
||||
cp -r "$writeable_orig_dir/$thing" "$out"
|
||||
done
|
||||
'';
|
||||
|
||||
# Takes an existing script and makes a initialization script that only runs if the output path
|
||||
# has not been built yet.
|
||||
mkInitScript = script: writeScript "init-writeable-paths" ''
|
||||
#!/bin/sh
|
||||
|
||||
out="${writeable_.sysPath}"
|
||||
|
||||
if [ ! -d "$out" ]; then
|
||||
|
||||
${script}
|
||||
|
||||
chown -R "${writeable_.owner}" "$out"
|
||||
chmod -R 744 "$out"
|
||||
|
||||
else
|
||||
echo Output directory already exists. Not building path: "$out"
|
||||
fi
|
||||
'';
|
||||
|
||||
in if appConfig.freezeWordPress
|
||||
then rec {
|
||||
# For a mostly frozen app, we install it as a package and set up writeable paths on first run.
|
||||
initScript = mkInitScript (initWriteablePathsFor package);
|
||||
package = runCommand "wordpress-app" {
|
||||
preferLocalBuild = true;
|
||||
} (buildPackageAt "$out");
|
||||
}
|
||||
else rec {
|
||||
# For fully writeable app, we skip package installation and write the app directly to the
|
||||
# writeable path on first run.
|
||||
initScript = mkInitScript (buildPackageAt package);
|
||||
package = writeable_.sysPath;
|
||||
}
|
113
modules/web-apps/wordpress/default-app-config.nix
Normal file
113
modules/web-apps/wordpress/default-app-config.nix
Normal file
|
@ -0,0 +1,113 @@
|
|||
let
|
||||
lib = (import <nixpkgs> {}).lib;
|
||||
in lib.makeExtensible (self: {
|
||||
domain = "wordpress-site.dev";
|
||||
|
||||
# Simple name used for directories, etc.
|
||||
# WARNING: Changing this after a deployment will change the location of data directories and will
|
||||
# likely result in a partial reset of your application. You must move data from the
|
||||
# previous app folders to the new ones.
|
||||
name = "wordpress-app";
|
||||
|
||||
description = "A Wordpress Site"; # Brief, one-line description or title
|
||||
tagline = "Deployed with Nixops";
|
||||
host = "www.${self.domain}";
|
||||
adminEmail = "admin@${self.domain}";
|
||||
|
||||
siteUrl = "${if self.enableHttps then "https" else "http"}://${self.host}";
|
||||
|
||||
# Hosts that get redirected to the primary host.
|
||||
hostRedirects = [self.domain];
|
||||
|
||||
# Configure timezone settings (http://php.net/manual/en/timezones.php)
|
||||
timezone = "UTC";
|
||||
|
||||
# WP-CLI settings for automatic install
|
||||
autoInstall = let
|
||||
adminConfig = import ./wordpress-admin.keys.nix;
|
||||
in lib.makeExtensible (innerSelf: {
|
||||
enable = false; # set to `true` to automatically install WordPress configuration
|
||||
inherit (adminConfig) adminUser adminPassword;
|
||||
});
|
||||
|
||||
wordpress = import ./wordpress.nix;
|
||||
plugins = import ./plugins.nix;
|
||||
themes = import ./themes.nix;
|
||||
|
||||
# Warning: Changing these after your site has been deployed will require manual
|
||||
# work on the server. We don't want to do anything that would lose
|
||||
# data so we leave that to you.
|
||||
freezeWordPress = true; # Can admins upgrade WordPress in the CMS?
|
||||
freezePlugins = true; # Can admins edit plugins in the CMS?
|
||||
freezeThemes = true; # Can admins edit themes in the CMS?
|
||||
|
||||
dbConfig = lib.makeExtensible (innerSelf: {
|
||||
isLocal = true; # if `true`, MySQL will be installed on the server.
|
||||
name = "wordpress"; # database name
|
||||
user = "root";
|
||||
password = "";
|
||||
host = "localhost";
|
||||
charset = "utf8mb4";
|
||||
tablePrefix = "wp_";
|
||||
});
|
||||
|
||||
wpConfig = lib.makeExtensible (innerSelf: {
|
||||
# Generate this file with `curl https://api.wordpress.org/secret-key/1.1/salt/ > wordpress-keys.php.secret`
|
||||
secrets = builtins.readFile ./wordpress-keys.php.secret;
|
||||
debugMode = false;
|
||||
extraConfig = ''
|
||||
define('WP_HOME', '${self.siteUrl}');
|
||||
define('WP_SITEURL', '${self.siteUrl}');
|
||||
'';
|
||||
|
||||
inherit (self) dbConfig;
|
||||
|
||||
template = import ./wp-config.nix;
|
||||
rendered = innerSelf.template innerSelf;
|
||||
});
|
||||
|
||||
|
||||
# Server settings
|
||||
enableHttps = true;
|
||||
maxUploadMb = 50;
|
||||
|
||||
# --- ADVANCED CONFIGURATION ---
|
||||
opcache = lib.makeExtensible (innerSelf: {
|
||||
enable = true;
|
||||
maxMemoryMb = 128;
|
||||
|
||||
# How often to invalidate timestamp cache. This is only used when the project
|
||||
# has non-frozen components (see above).
|
||||
# http://php.net/manual/en/opcache.configuration.php#ini.opcache.revalidate-freq
|
||||
revalidateFreqSec = 60;
|
||||
});
|
||||
|
||||
# PHP-FPM settings for the *dynamic* process manager: http://php.net/manual/en/install.fpm.configuration.php#pm
|
||||
phpFpmProcessSettings = lib.makeExtensible (innerSelf: {
|
||||
max_children = 10;
|
||||
start_servers = innerSelf.min_spare_servers; # WARNING: min_spare_servers <= start_servers <= max_spare_servers
|
||||
min_spare_servers = 2;
|
||||
max_spare_servers = 5;
|
||||
max_requests = 500;
|
||||
});
|
||||
|
||||
googlePageSpeed = lib.makeExtensible (innerSelf: {
|
||||
enable = true;
|
||||
cachePath = "/run/nginx-pagespeed-cache"; # /run/ is tmpfs and will keep cache in memory
|
||||
});
|
||||
|
||||
fastCgiCache = lib.makeExtensible (innerSelf: {
|
||||
enable = true;
|
||||
cachePath = "/run/nginx-fastcgi-cache"; # /run/ is tmpfs and will keep cache in memory
|
||||
});
|
||||
|
||||
php = lib.makeExtensible (innerSelf: {
|
||||
enableXDebug = false;
|
||||
|
||||
scriptMemoryLimitMb = 128;
|
||||
maxExecutionTimeSec = 300;
|
||||
|
||||
# sendmail_path configuration for php.ini files
|
||||
sendmailPath = "/run/wrappers/bin/sendmail -t -i";
|
||||
});
|
||||
})
|
5
modules/web-apps/wordpress/default.nix
Normal file
5
modules/web-apps/wordpress/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./module.nix
|
||||
];
|
||||
}
|
37
modules/web-apps/wordpress/install-wp.nix
Normal file
37
modules/web-apps/wordpress/install-wp.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
{ pkgs
|
||||
, config # system configuration
|
||||
, appConfig
|
||||
, appPackage
|
||||
, writeableDataPath
|
||||
}:
|
||||
pkgs.writeScript "install-wordpress.sh" ''
|
||||
#!${pkgs.stdenv.shell} -eu
|
||||
|
||||
if ! $('${pkgs.wp-cli}/bin/wp' core is-installed --path='${appPackage}' --allow-root); then
|
||||
echo 'Installing WordPress configuration for ${appConfig.host}'
|
||||
'${pkgs.wp-cli}/bin/wp' core install \
|
||||
--url='${appConfig.siteUrl}' \
|
||||
--title='${appConfig.description}' \
|
||||
--admin_user='${appConfig.autoInstall.adminUser}' \
|
||||
--admin_password='${appConfig.autoInstall.adminPassword}' \
|
||||
--admin_email='${appConfig.adminEmail}' \
|
||||
--path='${appPackage}' \
|
||||
--allow-root;
|
||||
chown -R '${config.services.nginx.user}' '${writeableDataPath}';
|
||||
else
|
||||
echo 'WordPress configuration already installed for ${appConfig.host}'
|
||||
fi
|
||||
|
||||
'${pkgs.wp-cli}/bin/wp' option update blogname '${appConfig.description}' \
|
||||
--path='${appPackage}' \
|
||||
--allow-root;
|
||||
|
||||
'${pkgs.wp-cli}/bin/wp' option update blogdescription '${appConfig.tagline}' \
|
||||
--path='${appPackage}' \
|
||||
--allow-root;
|
||||
|
||||
# TODO: Provide a list of plugins to be activated from plugins.nix
|
||||
'${pkgs.wp-cli}/bin/wp' plugin activate nginx-helper opcache \
|
||||
--path='${appPackage}' \
|
||||
--allow-root;
|
||||
''
|
79
modules/web-apps/wordpress/module.nix
Normal file
79
modules/web-apps/wordpress/module.nix
Normal file
|
@ -0,0 +1,79 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.wordpress;
|
||||
appConfig = (import ./default-app-config.nix).extend (self: super: {});
|
||||
writeableDataPath = "/var/lib/phpfpm/${appConfig.name}";
|
||||
phpFpmListen = "/run/phpfpm/wordpress-pool.sock";
|
||||
phpIni = import ./php-config.nix { inherit pkgs config appConfig; };
|
||||
enablePageSpeed = pkgs.stdenv.isLinux && appConfig.googlePageSpeed.enable;
|
||||
app = callPackage ./app.nix {
|
||||
inherit appConfig;
|
||||
writeable = {
|
||||
sysPath = writeableDataPath;
|
||||
owner = config.services.nginx.user;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.wordpress = {
|
||||
enable = mkEnableOption "Enable the WordPress module";
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [
|
||||
pkgs.wp-cli
|
||||
];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
# package = pkgs.callPackage ./nginx.nix { inherit enablePageSpeed; };
|
||||
# httpConfig = nginxConfig;
|
||||
# TODO: ajouter les locations pour wordpress
|
||||
};
|
||||
|
||||
systemd.services.init-writeable-paths = {
|
||||
description = "Initialize writeable directories for the app";
|
||||
before = [ "phpfpm.service" ];
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" "phpfpm.service" "nginx.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = app.initScript;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
systemd.services.install-wp = let
|
||||
deps = [ "init-writeable-paths.service" "mysql.service" ];
|
||||
in {
|
||||
enable = appConfig.autoInstall.enable;
|
||||
description = "Configure WordPress installation with WP-CLI";
|
||||
before = [ "nginx.service" ];
|
||||
after = deps;
|
||||
wants = deps;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = import ./install-wp.nix {
|
||||
inherit pkgs config appConfig writeableDataPath;
|
||||
appPackage = app.package;
|
||||
};
|
||||
};
|
||||
environment.PHP_INI_SCAN_DIR = let
|
||||
customIni = pkgs.writeTextDir "wp-cli-custom.ini" phpIni;
|
||||
in "${pkgs.php}/etc:${customIni}";
|
||||
};
|
||||
|
||||
services.phpfpm = {
|
||||
phpOptions = phpIni;
|
||||
pools.wordpress-pool = import ./phpfpm-conf.nix {
|
||||
inherit pkgs config phpFpmListen;
|
||||
processSettings = appConfig.phpFpmProcessSettings;
|
||||
};
|
||||
};
|
||||
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = pkgs.mariadb;
|
||||
};
|
||||
}
|
34
modules/web-apps/wordpress/php-config.nix
Normal file
34
modules/web-apps/wordpress/php-config.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{ pkgs
|
||||
, config # system configuration
|
||||
, appConfig
|
||||
}:
|
||||
|
||||
assert appConfig.php.scriptMemoryLimitMb > appConfig.maxUploadMb;
|
||||
|
||||
''
|
||||
memory_limit ${toString appConfig.php.scriptMemoryLimitMb}M
|
||||
|
||||
extension = "${pkgs.phpPackages.imagick}/lib/php/extensions/imagick.so"
|
||||
|
||||
${pkgs.lib.optionalString appConfig.opcache.enable ''
|
||||
zend_extension = "${config.services.phpfpm.phpPackage}/lib/php/extensions/opcache.so"
|
||||
''}
|
||||
|
||||
${pkgs.lib.optionalString appConfig.php.enableXDebug ''
|
||||
; WARNING: Be sure to load opcache *before* xdebug (http://us3.php.net/manual/en/opcache.installation.php).
|
||||
zend_extension = "${pkgs.phpPackages.xdebug}/lib/php/extensions/xdebug.so"
|
||||
''}
|
||||
|
||||
upload_max_filesize = ${toString appConfig.maxUploadMb}M
|
||||
post_max_size = ${toString appConfig.maxUploadMb}M
|
||||
max_execution_time ${toString appConfig.php.maxExecutionTimeSec}
|
||||
|
||||
date.timezone = "${appConfig.timezone}"
|
||||
sendmail_path = ${appConfig.php.sendmailPath}
|
||||
|
||||
${import ./opcache-config.nix (appConfig.opcache // {
|
||||
# Enable timestamp validation if the setup is not entirely frozen (managed by Nix).
|
||||
validateTimestamps = ! builtins.all (x: x)
|
||||
[appConfig.freezeWordPress appConfig.freezePlugins appConfig.freezeThemes];
|
||||
})}
|
||||
''
|
12
modules/web-apps/wordpress/phpfpm-conf.nix
Normal file
12
modules/web-apps/wordpress/phpfpm-conf.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{ pkgs, config, phpFpmListen, processSettings }:
|
||||
{
|
||||
inherit (config.services.nginx) user group;
|
||||
settings = {
|
||||
"listen.owner" = config.services.nginx.user;
|
||||
"listen.group" = config.services.nginx.group;
|
||||
"listen.mode" = 660;
|
||||
"pm" = "dynamic";
|
||||
"catch_workers_output" = "yes";
|
||||
} // processSettings;
|
||||
listen = phpFpmListen;
|
||||
}
|
14
modules/web-apps/wordpress/plugins.nix
Normal file
14
modules/web-apps/wordpress/plugins.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
# A list of your WordPress plugins.
|
||||
{ callPackage, ... }:
|
||||
let
|
||||
utils = callPackage ./utils.nix {};
|
||||
getPlugin = utils.getPlugin;
|
||||
|
||||
requiredPlugins = [
|
||||
(getPlugin "opcache" "0.3.1" "18x6fnfc7ka4ynxv4z3rf4011ivqc0qy0dsd6i4lxa113jjyqz6d")
|
||||
(getPlugin "nginx-helper" "1.9.10" "1n887qz9rzs8yj069wva6cirp6y46a49wspzja4grdj2qirr4hky")
|
||||
];
|
||||
in requiredPlugins ++ [
|
||||
(getPlugin "akismet" "3.3" "02vsjnr7bs54a744p64rx7jwlbcall6nhh1mv6w54zbwj4ygqz68")
|
||||
(getPlugin "jetpack" "4.8.2" "17bvkcb17dx969a30j0axb5kqzfxnx1sqkcdwwrski9gh7ihabqk")
|
||||
]
|
8
modules/web-apps/wordpress/themes.nix
Normal file
8
modules/web-apps/wordpress/themes.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
# A list of your WordPress themes.
|
||||
{ callPackage, ... }:
|
||||
let
|
||||
utils = callPackage ./utils.nix {};
|
||||
getTheme = utils.getTheme;
|
||||
in [
|
||||
(getTheme "twentyseventeen" "1.1" "1xsdz1s68mavz9i4lhckh7rqw266jqm5mn3ql1gbz03zf6ghf982")
|
||||
]
|
15
modules/web-apps/wordpress/utils.nix
Normal file
15
modules/web-apps/wordpress/utils.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
traced = x: builtins.trace x x;
|
||||
required = arg: help: builtins.abort "${arg} is required: ${help}";
|
||||
|
||||
# Converts a set into a string
|
||||
# pkgs is nixpkgs
|
||||
# sep is a string separator to place between each field
|
||||
# mapFn is (string -> string -> string) taking key and value for each attribute
|
||||
# attrs is the set to process
|
||||
setToString = pkgs: sep: mapFn: attrs: pkgs.lib.concatStringsSep sep (
|
||||
pkgs.lib.mapAttrsToList
|
||||
(key: val: if builtins.isInt val || builtins.isString val then mapFn key val else "")
|
||||
attrs
|
||||
);
|
||||
}
|
7
modules/web-apps/wordpress/wordpress.nix
Normal file
7
modules/web-apps/wordpress/wordpress.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{ fetchzip, runCommand, ... }:
|
||||
let
|
||||
version = "4.8";
|
||||
in fetchzip {
|
||||
url = "https://wordpress.org/wordpress-${version}.tar.gz";
|
||||
sha256 = "1myflpa9pxcghnhjfd0ahqpsvgcwh3szk2k8w2x7qmvfll69n3j9";
|
||||
}
|
Loading…
Add table
Reference in a new issue