commit
f222d98746
@ -0,0 +1,335 @@ |
||||
<chapter xmlns="http://docbook.org/ns/docbook" |
||||
xmlns:xlink="http://www.w3.org/1999/xlink" |
||||
xmlns:xi="http://www.w3.org/2001/XInclude" |
||||
version="5.0" |
||||
xml:id="sec-grsecurity"> |
||||
|
||||
<title>Grsecurity/PaX</title> |
||||
|
||||
<para> |
||||
Grsecurity/PaX is a set of patches against the Linux kernel that make it |
||||
harder to exploit bugs. The patchset includes protections such as |
||||
enforcement of non-executable memory, address space layout randomization, |
||||
and chroot jail hardening. These and other |
||||
<link xlink:href="https://grsecurity.net/features.php">features</link> |
||||
render entire classes of exploits inert without additional efforts on the |
||||
part of the adversary. |
||||
</para> |
||||
|
||||
<para> |
||||
The NixOS grsecurity/PaX module is designed with casual users in mind and is |
||||
intended to be compatible with normal desktop usage, without unnecessarily |
||||
compromising security. The following sections describe the configuration |
||||
and administration of a grsecurity/PaX enabled NixOS system. For |
||||
more comprehensive coverage, please refer to the |
||||
<link xlink:href="https://en.wikibooks.org/wiki/Grsecurity">grsecurity wikibook</link> |
||||
and the |
||||
<link xlink:href="https://wiki.archlinux.org/index.php/Grsecurity">Arch |
||||
Linux wiki page on grsecurity</link>. |
||||
|
||||
<note><para>grsecurity/PaX is only available for the latest linux -stable |
||||
kernel; patches against older kernels are available from upstream only for |
||||
a fee.</para></note> |
||||
<note><para>We standardise on a desktop oriented configuration primarily due |
||||
to lack of resources. The grsecurity/PaX configuration state space is huge |
||||
and each configuration requires quite a bit of testing to ensure that the |
||||
resulting packages work as advertised. Defining additional package sets |
||||
would likely result in a large number of functionally broken packages, to |
||||
nobody's benefit.</para></note>. |
||||
</para> |
||||
|
||||
<sect1 xml:id="sec-grsec-enable"><title>Enabling grsecurity/PaX</title> |
||||
|
||||
<para> |
||||
To make use of grsecurity/PaX on NixOS, add the following to your |
||||
<filename>configuration.nix</filename>: |
||||
<programlisting> |
||||
security.grsecurity.enable = true; |
||||
</programlisting> |
||||
followed by |
||||
<programlisting> |
||||
# nixos-rebuild boot |
||||
# reboot |
||||
</programlisting> |
||||
For most users, further configuration should be unnecessary. All users |
||||
are encouraged to look over <xref linkend="sec-grsec-security" /> before |
||||
using the system, however. If you experience problems, please refer to |
||||
<xref linkend="sec-grsec-issues" />. |
||||
</para> |
||||
|
||||
<para> |
||||
Once booted into the new system, you can optionally use |
||||
<command>paxtest</command> to exercise various PaX features: |
||||
<screen><![CDATA[ |
||||
# nix-shell -p paxtest --command 'paxtest blackhat' |
||||
Executable anonymous mapping : Killed |
||||
Executable bss : Killed |
||||
# ... remaining output truncated for brevity |
||||
]]></screen> |
||||
</para> |
||||
|
||||
</sect1> |
||||
|
||||
<sect1 xml:id="sec-grsec-declarative-tuning"><title>Declarative tuning</title> |
||||
|
||||
<para> |
||||
The default configuration mode is strictly declarative. Some features |
||||
simply cannot be changed at all after boot, while others are locked once the |
||||
system is up and running. Moreover, changes to the configuration enter |
||||
into effect only upon booting into the new system. |
||||
</para> |
||||
|
||||
<para> |
||||
The NixOS module exposes a limited number of options for tuning the behavior |
||||
of grsecurity/PaX. These are options thought to be of particular interest |
||||
to most users. For experts, further tuning is possible via |
||||
<option>boot.kernelParams</option> (see |
||||
<xref linkend="sec-grsec-kernel-params" />) and |
||||
<option>boot.kernel.sysctl."kernel.grsecurity.*"</option> (the wikibook |
||||
contains an <link xlink:href="https://en.wikibooks.org/wiki/Grsecurity/Appendix/Sysctl_Options"> |
||||
exhaustive listing of grsecurity sysctl tunables</link>). |
||||
</para> |
||||
|
||||
</sect1> |
||||
|
||||
<sect1 xml:id="sec-grsec-manual-tuning"><title>Manual tuning</title> |
||||
|
||||
<para> |
||||
To permit manual tuning of grsecurity runtime parameters, set: |
||||
<programlisting> |
||||
security.grsecurity.lockTunables = false; |
||||
</programlisting> |
||||
Once booted into this system, grsecurity features that have a corresponding |
||||
sysctl tunable can be changed without rebooting, either by switching into |
||||
a new system profile or via the <command>sysctl</command> utility. |
||||
</para> |
||||
|
||||
<para> |
||||
To lock all grsecurity tunables until the next boot, do: |
||||
<screen> |
||||
# systemctl start grsec-lock |
||||
</screen> |
||||
</para> |
||||
|
||||
</sect1> |
||||
|
||||
<sect1 xml:id="sec-grsec-security"><title>Security considerations</title> |
||||
|
||||
<para> |
||||
The NixOS kernel is built using upstream's recommended settings for a |
||||
desktop deployment that generally favours security over performance. This |
||||
section details deviations from upstream's recommendations that may |
||||
compromise operational security. |
||||
|
||||
<warning><para>There may be additional problems not covered here!</para> |
||||
</warning>. |
||||
</para> |
||||
|
||||
<itemizedlist> |
||||
|
||||
<listitem><para> |
||||
The following hardening features are disabled in the NixOS kernel: |
||||
<itemizedlist> |
||||
<listitem><para>Kernel symbol hiding: rendered useless by redistributing |
||||
kernel objects.</para></listitem> |
||||
|
||||
<listitem><para>Randomization of kernel structures: rendered useless by |
||||
redistributing kernel objects.</para></listitem> |
||||
|
||||
<listitem><para>TCP simultaneous OPEN connection is permitted: breaking |
||||
strict TCP conformance is inappropriate for a general purpose kernel. |
||||
The trade-off is that an attacker may be able to deny outgoing |
||||
connections if they are able to guess the source port allocated by your |
||||
OS for that connection <emphasis>and</emphasis> also manage to initiate |
||||
a TCP simultaneous OPEN on that port before the connection is actually |
||||
established.</para></listitem> |
||||
|
||||
<listitem><para><filename class="directory">/sys</filename> hardening: |
||||
breaks systemd.</para></listitem> |
||||
|
||||
<listitem><para>Trusted path execution: a desirable feature, but |
||||
requires some more work to operate smoothly on NixOS.</para></listitem> |
||||
</itemizedlist> |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
The NixOS module conditionally weakens <command>chroot</command> |
||||
restrictions to accommodate NixOS lightweight containers and sandboxed Nix |
||||
builds. This is problematic if the deployment also runs a privileged |
||||
network facing process that <emphasis>relies</emphasis> on |
||||
<command>chroot</command> for isolation. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
The NixOS kernel is patched to allow usermode helpers from anywhere in the |
||||
Nix store. A usermode helper is an executable called by the kernel in |
||||
certain circumstances, e.g., <command>modprobe</command>. Vanilla |
||||
grsecurity only allows usermode helpers from paths typically owned by the |
||||
super user. The NixOS kernel allows an attacker to inject malicious code |
||||
into the Nix store which could then be executed by the kernel as a |
||||
usermode helper. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
The following features are disabled because they overlap with |
||||
vanilla kernel mechanisms: |
||||
|
||||
<itemizedlist> |
||||
<listitem><para><filename class="directory">/proc</filename> hardening: |
||||
use <option>security.hideProcessInformation</option> instead. This |
||||
trades weaker protection for greater compatibility. |
||||
</para></listitem> |
||||
|
||||
<listitem><para><command>dmesg</command> restrictions: |
||||
use <option>boot.kernel.sysctl."kernel.dmesg_restrict"</option> instead |
||||
</para></listitem> |
||||
</itemizedlist> |
||||
</para></listitem> |
||||
|
||||
</itemizedlist> |
||||
|
||||
</sect1> |
||||
|
||||
<sect1 xml:id="sec-grsec-custom-kernel"><title>Using a custom grsecurity/PaX kernel</title> |
||||
|
||||
<para> |
||||
The NixOS kernel is likely to be either too permissive or too restrictive |
||||
for many deployment scenarios. In addition to producing a kernel more |
||||
suitable for a particular deployment, a custom kernel may improve security |
||||
by depriving an attacker the ability to study the kernel object code, adding |
||||
yet more guesswork to successfully carry out certain exploits. |
||||
</para> |
||||
|
||||
<para> |
||||
To use a custom kernel with upstream's recommended settings for server |
||||
deployments: |
||||
<programlisting> |
||||
boot.kernelPackages = |
||||
let |
||||
kernel = pkgs.linux_grsec_nixos.override { |
||||
extraConfig = '' |
||||
GRKERNSEC y |
||||
PAX y |
||||
GRKERNSEC_CONFIG_AUTO y |
||||
GRKERNSEC_CONFIG_SERVER y |
||||
GRKERNSEC_CONFIG_SECURITY y |
||||
''; |
||||
}; |
||||
self = pkgs.linuxPackagesFor kernel self; |
||||
in self; |
||||
</programlisting> |
||||
The wikibook provides an exhaustive listing of |
||||
<link xlink:href="https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options">kernel configuration options</link>. |
||||
</para> |
||||
|
||||
<para> |
||||
The NixOS module makes several assumptions about the kernel and so may be |
||||
incompatible with your customised kernel. Most of these assumptions are |
||||
encoded as assertions — mismatches should ideally result in a build |
||||
failure. Currently, the only way to work around incompatibilities is to |
||||
eschew the NixOS module and do all configuration yourself. |
||||
</para> |
||||
|
||||
</sect1> |
||||
|
||||
<sect1 xml:id="sec-grsec-pax-flags"><title>Per-executable PaX flags</title> |
||||
|
||||
<para> |
||||
Manual tuning of per-file PaX flags for executables in the Nix store is |
||||
impossible on a properly configured system. If a package in Nixpkgs fails |
||||
due to PaX, that is a bug in the package recipe and should be reported to |
||||
the maintainer (including relevant <command>dmesg</command> output). |
||||
</para> |
||||
|
||||
<para> |
||||
For executables installed outside of the Nix store, PaX flags can be set |
||||
using the <command>paxctl</command> utility: |
||||
<programlisting> |
||||
paxctl -czem <replaceable>foo</replaceable> |
||||
</programlisting> |
||||
|
||||
<warning> |
||||
<para><command>paxctl</command> overwrites files in-place.</para> |
||||
</warning> |
||||
|
||||
Equivalently, on file systems that support extended attributes: |
||||
<programlisting> |
||||
setfattr -n user.pax.flags -v em <replaceable>foo</replaceable> |
||||
</programlisting> |
||||
|
||||
<!-- TODO: PaX flags via RBAC policy --> |
||||
</para> |
||||
|
||||
</sect1> |
||||
|
||||
<sect1 xml:id="sec-grsec-issues"><title>Issues and work-arounds</title> |
||||
|
||||
<itemizedlist> |
||||
<listitem><para>Virtualization: KVM is the preferred virtualization |
||||
solution. Xen, Virtualbox, and VMWare are |
||||
<emphasis>unsupported</emphasis> and most likely require a custom kernel. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
Attaching <command>gdb</command> to a running process is disallowed by |
||||
default: unprivileged users can only ptrace processes that are children of |
||||
the ptracing process. To relax this restriction, set |
||||
<programlisting> |
||||
boot.kernel.sysctl."kernel.grsecurity.harden_ptrace" = 0; |
||||
</programlisting> |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
Overflows in boot critical code (e.g., the root filesystem module) can |
||||
render the system unbootable. Work around by setting |
||||
<programlisting> |
||||
boot.kernel.kernelParams = [ "pax_size_overflow_report_only" ]; |
||||
</programlisting> |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
The <citerefentry><refentrytitle>modify_ldt |
||||
</refentrytitle><manvolnum>2</manvolnum></citerefentry> syscall is disabled |
||||
by default. This restriction can interfere with programs designed to run |
||||
legacy 16-bit or segmented 32-bit code. To support applications that rely |
||||
on this syscall, set |
||||
<programlisting> |
||||
boot.kernel.sysctl."kernel.modify_ldt" = 1; |
||||
</programlisting> |
||||
</para></listitem> |
||||
|
||||
</itemizedlist> |
||||
|
||||
</sect1> |
||||
|
||||
<sect1 xml:id="sec-grsec-kernel-params"><title>Grsecurity/PaX kernel parameters</title> |
||||
|
||||
<para> |
||||
The NixOS kernel supports the following kernel command line parameters: |
||||
<itemizedlist> |
||||
<listitem><para> |
||||
<literal>pax_nouderef</literal>: disable UDEREF (separate kernel and |
||||
user address spaces). |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
<literal>pax_weakuderef</literal>: enable a faster but |
||||
weaker variant of UDEREF on 64-bit processors with PCID support |
||||
(check <code>grep pcid /proc/cpuinfo</code>). |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
<literal>pax_sanitize_slab={off|fast|full}</literal>: control kernel |
||||
slab object sanitization |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
<literal>pax_size_overflow_report_only</literal>: log size overflow |
||||
violations but leave the violating task running |
||||
</para></listitem> |
||||
</itemizedlist> |
||||
</para> |
||||
|
||||
</sect1> |
||||
|
||||
</chapter> |
@ -0,0 +1,212 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
with lib; |
||||
|
||||
let |
||||
cfg = config.services.gocd-agent; |
||||
in { |
||||
options = { |
||||
services.gocd-agent = { |
||||
enable = mkEnableOption "gocd-agent"; |
||||
|
||||
user = mkOption { |
||||
default = "gocd-agent"; |
||||
type = types.str; |
||||
description = '' |
||||
User the Go.CD agent should execute under. |
||||
''; |
||||
}; |
||||
|
||||
group = mkOption { |
||||
default = "gocd-agent"; |
||||
type = types.str; |
||||
description = '' |
||||
If the default user "gocd-agent" is configured then this is the primary |
||||
group of that user. |
||||
''; |
||||
}; |
||||
|
||||
extraGroups = mkOption { |
||||
type = types.listOf types.str; |
||||
default = [ ]; |
||||
example = [ "wheel" "docker" ]; |
||||
description = '' |
||||
List of extra groups that the "gocd-agent" user should be a part of. |
||||
''; |
||||
}; |
||||
|
||||
packages = mkOption { |
||||
default = [ pkgs.stdenv pkgs.jre config.programs.ssh.package pkgs.nix ]; |
||||
type = types.listOf types.package; |
||||
description = '' |
||||
Packages to add to PATH for the Go.CD agent process. |
||||
''; |
||||
}; |
||||
|
||||
agentConfig = mkOption { |
||||
default = ""; |
||||
type = types.str; |
||||
example = '' |
||||
agent.auto.register.resources=ant,java |
||||
agent.auto.register.environments=QA,Performance |
||||
agent.auto.register.hostname=Agent01 |
||||
''; |
||||
description = '' |
||||
Agent registration configuration. |
||||
''; |
||||
}; |
||||
|
||||
goServer = mkOption { |
||||
default = "127.0.0.1"; |
||||
type = types.str; |
||||
description = '' |
||||
Address of GoCD Server to attach the Go.CD Agent to. |
||||
''; |
||||
}; |
||||
|
||||
goServerPort = mkOption { |
||||
default = 8153; |
||||
type = types.int; |
||||
description = '' |
||||
Port that Go.CD Server is Listening on. |
||||
''; |
||||
}; |
||||
|
||||
workDir = mkOption { |
||||
default = "/var/lib/go-agent"; |
||||
type = types.str; |
||||
description = '' |
||||
Specifies the working directory in which the Go.CD agent java archive resides. |
||||
''; |
||||
}; |
||||
|
||||
heapSize = mkOption { |
||||
default = "128m"; |
||||
type = types.str; |
||||
description = '' |
||||
Specifies the java heap memory size for the Go.CD agent java process. |
||||
''; |
||||
}; |
||||
|
||||
maxMemory = mkOption { |
||||
default = "256m"; |
||||
type = types.str; |
||||
description = '' |
||||
Specifies the java maximum memory size for the Go.CD agent java process. |
||||
''; |
||||
}; |
||||
|
||||
startupOptions = mkOption { |
||||
default = [ |
||||
"-Xms${cfg.heapSize}" |
||||
"-Xmx${cfg.maxMemory}" |
||||
"-Djava.io.tmpdir=/tmp" |
||||
"-Dcruise.console.publish.interval=10" |
||||
"-Djava.security.egd=file:/dev/./urandom" |
||||
]; |
||||
description = '' |
||||
Specifies startup command line arguments to pass to Go.CD agent |
||||
java process. Example contains debug and gcLog arguments. |
||||
''; |
||||
}; |
||||
|
||||
extraOptions = mkOption { |
||||
default = [ ]; |
||||
example = [ |
||||
"-X debug" |
||||
"-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006" |
||||
"-verbose:gc" |
||||
"-Xloggc:go-agent-gc.log" |
||||
"-XX:+PrintGCTimeStamps" |
||||
"-XX:+PrintTenuringDistribution" |
||||
"-XX:+PrintGCDetails" |
||||
"-XX:+PrintGC" |
||||
]; |
||||
description = '' |
||||
Specifies additional command line arguments to pass to Go.CD agent |
||||
java process. Example contains debug and gcLog arguments. |
||||
''; |
||||
}; |
||||
|
||||
environment = mkOption { |
||||
default = { }; |
||||
type = with types; attrsOf str; |
||||
description = '' |
||||
Additional environment variables to be passed to the Go.CD agent process. |
||||
As a base environment, Go.CD agent receives NIX_PATH from |
||||
<option>environment.sessionVariables</option>, NIX_REMOTE is set to |
||||
"daemon". |
||||
''; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
config = mkIf cfg.enable { |
||||
users.extraGroups = optional (cfg.group == "gocd-agent") { |
||||
name = "gocd-agent"; |
||||
gid = config.ids.gids.gocd-agent; |
||||
}; |
||||
|
||||
users.extraUsers = optional (cfg.user == "gocd-agent") { |
||||
name = "gocd-agent"; |
||||
description = "gocd-agent user"; |
||||
createHome = true; |
||||
home = cfg.workDir; |
||||
group = cfg.group; |
||||
extraGroups = cfg.extraGroups; |
||||
useDefaultShell = true; |
||||
uid = config.ids.uids.gocd-agent; |
||||
}; |
||||
|
||||
systemd.services.gocd-agent = { |
||||
description = "GoCD Agent"; |
||||
after = [ "network.target" ]; |
||||
wantedBy = [ "multi-user.target" ]; |
||||
|
||||
environment = |
||||
let |
||||
selectedSessionVars = |
||||
lib.filterAttrs (n: v: builtins.elem n [ "NIX_PATH" ]) |
||||
config.environment.sessionVariables; |
||||
in |
||||
selectedSessionVars // |
||||
{ |
||||
NIX_REMOTE = "daemon"; |
||||
AGENT_WORK_DIR = cfg.workDir; |
||||
AGENT_STARTUP_ARGS = ''${concatStringsSep " " cfg.startupOptions}''; |
||||
LOG_DIR = cfg.workDir; |
||||
LOG_FILE = "${cfg.workDir}/go-agent-start.log"; |
||||
} // |
||||
cfg.environment; |
||||
|
||||
path = cfg.packages; |
||||
|
||||
script = '' |
||||
MPATH="''${PATH}"; |
||||
source /etc/profile |
||||
export PATH="''${MPATH}:''${PATH}"; |
||||
|
||||
if ! test -f ~/.nixpkgs/config.nix; then |
||||
mkdir -p ~/.nixpkgs/ |
||||
echo "{ allowUnfree = true; }" > ~/.nixpkgs/config.nix |
||||
fi |
||||
|
||||
mkdir -p config |
||||
rm -f config/autoregister.properties |
||||
ln -s "${pkgs.writeText "autoregister.properties" cfg.agentConfig}" config/autoregister.properties |
||||
|
||||
${pkgs.git}/bin/git config --global --add http.sslCAinfo /etc/ssl/certs/ca-certificates.crt |
||||
${pkgs.jre}/bin/java ${concatStringsSep " " cfg.startupOptions} \ |
||||
${concatStringsSep " " cfg.extraOptions} \ |
||||
-jar ${pkgs.gocd-agent}/go-agent/agent-bootstrapper.jar \ |
||||
${cfg.goServer} \ |
||||
${toString cfg.goServerPort} |
||||
''; |
||||
|
||||
serviceConfig = { |
||||
User = cfg.user; |
||||
WorkingDirectory = cfg.workDir; |
||||
}; |
||||
}; |
||||
}; |
||||
} |
@ -0,0 +1,183 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
with lib; |
||||
|
||||
let |
||||
cfg = config.services.gocd-server; |
||||
in { |
||||
options = { |
||||
services.gocd-server = { |
||||
enable = mkEnableOption "gocd-server"; |
||||
|
||||
user = mkOption { |
||||
default = "gocd-server"; |
||||
type = types.str; |
||||
description = '' |
||||
User the Go.CD server should execute under. |
||||
''; |
||||
}; |
||||
|
||||
group = mkOption { |
||||
default = "gocd-server"; |
||||
type = types.str; |
||||
description = '' |
||||
If the default user "gocd-server" is configured then this is the primary group of that user. |
||||
''; |
||||
}; |
||||
|
||||
extraGroups = mkOption { |
||||
default = [ ]; |
||||
example = [ "wheel" "docker" ]; |
||||
description = '' |
||||
List of extra groups that the "gocd-server" user should be a part of. |
||||
''; |
||||
}; |
||||
|
||||
listenAddress = mkOption { |
||||
default = "0.0.0.0"; |
||||
example = "localhost"; |
||||
type = types.str; |
||||
description = '' |
||||
Specifies the bind address on which the Go.CD server HTTP interface listens. |
||||
''; |
||||
}; |
||||
|
||||
port = mkOption { |
||||
default = 8153; |
||||
type = types.int; |
||||
description = '' |
||||
Specifies port number on which the Go.CD server HTTP interface listens. |
||||
''; |
||||
}; |
||||
|
||||
sslPort = mkOption { |
||||
default = 8154; |
||||
type = types.int; |
||||
description = '' |
||||
Specifies port number on which the Go.CD server HTTPS interface listens. |
||||
''; |
||||
}; |
||||
|
||||
workDir = mkOption { |
||||
default = "/var/lib/go-server"; |
||||
type = types.str; |
||||
description = '' |
||||
Specifies the working directory in which the Go.CD server java archive resides. |
||||
''; |
||||
}; |
||||
|
||||
packages = mkOption { |
||||
default = [ pkgs.stdenv pkgs.jre config.programs.ssh.package pkgs.nix ]; |
||||
type = types.listOf types.package; |
||||
description = '' |
||||
Packages to add to PATH for the Go.CD server's process. |
||||
''; |
||||
}; |
||||
|
||||
heapSize = mkOption { |
||||
default = "512m"; |
||||
type = types.str; |
||||
description = '' |
||||
Specifies the java heap memory size for the Go.CD server's java process. |
||||
''; |
||||
}; |
||||
|
||||
maxMemory = mkOption { |
||||
default = "1024m"; |
||||
type = types.str; |
||||
description = '' |
||||
Specifies the java maximum memory size for the Go.CD server's java process. |
||||
''; |
||||
}; |
||||
|
||||
extraOptions = mkOption { |
||||
default = [ |
||||
"-Xms${cfg.heapSize}" |
||||
"-Xmx${cfg.maxMemory}" |
||||
"-Dcruise.listen.host=${cfg.listenAddress}" |
||||
"-Duser.language=en" |
||||
"-Djruby.rack.request.size.threshold.bytes=30000000" |
||||
"-Duser.country=US" |
||||
"-Dcruise.config.dir=${cfg.workDir}/conf" |
||||
"-Dcruise.config.file=${cfg.workDir}/conf/cruise-config.xml" |
||||
"-Dcruise.server.port=${toString cfg.port}" |
||||
"-Dcruise.server.ssl.port=${toString cfg.sslPort}" |
||||
]; |
||||
example = [ |
||||
"-X debug" |
||||
"-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" |
||||
"-verbose:gc" |
||||
"-Xloggc:go-server-gc.log" |
||||
"-XX:+PrintGCTimeStamps" |
||||
"-XX:+PrintTenuringDistribution" |
||||
"-XX:+PrintGCDetails" |
||||
"-XX:+PrintGC" |
||||
]; |
||||
description = '' |
||||
Specifies additional command line arguments to pass to Go.CD server's |
||||
java process. Example contains debug and gcLog arguments. |
||||
''; |
||||
}; |
||||
|
||||
environment = mkOption { |
||||
default = { }; |
||||
type = with types; attrsOf str; |
||||
description = '' |
||||
Additional environment variables to be passed to the gocd-server process. |
||||
As a base environment, gocd-server receives NIX_PATH from |
||||
<option>environment.sessionVariables</option>, NIX_REMOTE is set to |
||||
"daemon". |
||||
''; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
config = mkIf cfg.enable { |
||||
users.extraGroups = optional (cfg.group == "gocd-server") { |
||||
name = "gocd-server"; |
||||
gid = config.ids.gids.gocd-server; |
||||
}; |
||||
|
||||
users.extraUsers = optional (cfg.user == "gocd-server") { |
||||
name = "gocd-server"; |
||||
description = "gocd-server user"; |
||||
createHome = true; |
||||
home = cfg.workDir; |
||||
group = cfg.group; |
||||
extraGroups = cfg.extraGroups; |
||||
useDefaultShell = true; |
||||
uid = config.ids.uids.gocd-server; |
||||
}; |
||||
|
||||
systemd.services.gocd-server = { |
||||
description = "GoCD Server"; |
||||
after = [ "network.target" ]; |
||||
wantedBy = [ "multi-user.target" ]; |
||||
|
||||
environment = |
||||
let |
||||
selectedSessionVars = |
||||
lib.filterAttrs (n: v: builtins.elem n [ "NIX_PATH" ]) |
||||
config.environment.sessionVariables; |
||||
in |
||||
selectedSessionVars // |
||||
{ NIX_REMOTE = "daemon"; |
||||
} // |
||||
cfg.environment; |
||||
|
||||
path = cfg.packages; |
||||
|
||||
script = '' |
||||
${pkgs.git}/bin/git config --global --add http.sslCAinfo /etc/ssl/certs/ca-certificates.crt |
||||
${pkgs.jre}/bin/java -server ${concatStringsSep " " cfg.extraOptions} \ |
||||
-jar ${pkgs.gocd-server}/go-server/go.jar |
||||
''; |
||||
|
||||
serviceConfig = { |
||||
User = cfg.user; |
||||
Group = cfg.group; |
||||
WorkingDirectory = cfg.workDir; |
||||
}; |
||||
}; |
||||
}; |
||||
} |
@ -0,0 +1,569 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
with lib; |
||||
let |
||||
cfg = config.services.tt-rss; |
||||
|
||||
configVersion = 26; |
||||
|
||||
boolToString = b: if b then "true" else "false"; |
||||
|
||||
cacheDir = "cache"; |
||||
lockDir = "lock"; |
||||
feedIconsDir = "feed-icons"; |
||||
|
||||
dbPort = if cfg.database.port == null |
||||
then (if cfg.database.type == "pgsql" then 5432 else 3306) |
||||
else cfg.database.port; |
||||
|
||||
poolName = "tt-rss"; |
||||
virtualHostName = "tt-rss"; |
||||
|
||||
tt-rss-config = pkgs.writeText "config.php" '' |
||||
<?php |
||||
|
||||
define('PHP_EXECUTABLE', '${pkgs.php}/bin/php'); |
||||
|
||||
define('LOCK_DIRECTORY', '${lockDir}'); |
||||
define('CACHE_DIR', '${cacheDir}'); |
||||
define('ICONS_DIR', '${feedIconsDir}'); |
||||
define('ICONS_URL', '${feedIconsDir}'); |
||||
define('SELF_URL_PATH', '${cfg.selfUrlPath}'); |
||||
|
||||
define('MYSQL_CHARSET', 'UTF8'); |
||||
|
||||
define('DB_TYPE', '${cfg.database.type}'); |
||||
define('DB_HOST', '${cfg.database.host}'); |
||||
define('DB_USER', '${cfg.database.user}'); |
||||
define('DB_NAME', '${cfg.database.name}'); |
||||
define('DB_PASS', '${escape ["'" "\\"] cfg.database.password}'); |
||||
define('DB_PORT', '${toString dbPort}'); |
||||
|
||||
define('AUTH_AUTO_CREATE', ${boolToString cfg.auth.autoCreate}); |
||||
define('AUTH_AUTO_LOGIN', ${boolToString cfg.auth.autoLogin}); |
||||
|
||||
define('FEED_CRYPT_KEY', '${escape ["'" "\\"] cfg.feedCryptKey}'); |
||||
|
||||
|
||||
define('SINGLE_USER_MODE', ${boolToString cfg.singleUserMode}); |
||||
|
||||
define('SIMPLE_UPDATE_MODE', ${boolToString cfg.simpleUpdateMode}); |
||||
define('CHECK_FOR_UPDATES', ${boolToString cfg.checkForUpdates}); |
||||
|
||||
define('FORCE_ARTICLE_PURGE', ${toString cfg.forceArticlePurge}); |
||||
define('SESSION_COOKIE_LIFETIME', ${toString cfg.sessionCookieLifetime}); |
||||
define('ENABLE_GZIP_OUTPUT', ${boolToString cfg.enableGZipOutput}); |
||||
|
||||
define('PLUGINS', '${builtins.concatStringsSep "," cfg.plugins}'); |
||||
|
||||
define('LOG_DESTINATION', '${cfg.logDestination}'); |
||||
define('CONFIG_VERSION', ${toString configVersion}); |
||||
|
||||
|
||||
define('PUBSUBHUBBUB_ENABLED', ${boolToString cfg.pubSubHubbub.enable}); |
||||
define('PUBSUBHUBBUB_HUB', '${cfg.pubSubHubbub.hub}'); |
||||
|
||||
define('SPHINX_SERVER', '${cfg.sphinx.server}'); |
||||
define('SPHINX_INDEX', '${builtins.concatStringsSep "," cfg.sphinx.index}'); |
||||
|
||||
define('ENABLE_REGISTRATION', ${boolToString cfg.registration.enable}); |
||||
define('REG_NOTIFY_ADDRESS', '${cfg.registration.notifyAddress}'); |
||||
define('REG_MAX_USERS', ${toString cfg.registration.maxUsers}); |
||||
|
||||
define('SMTP_SERVER', '${cfg.email.server}'); |
||||
define('SMTP_LOGIN', '${cfg.email.login}'); |
||||
define('SMTP_PASSWORD', '${escape ["'" "\\"] cfg.email.password}'); |
||||
define('SMTP_SECURE', '${cfg.email.security}'); |
||||
|
||||
define('SMTP_FROM_NAME', '${escape ["'" "\\"] cfg.email.fromName}'); |
||||
define('SMTP_FROM_ADDRESS', '${escape ["'" "\\"] cfg.email.fromAddress}'); |
||||
define('DIGEST_SUBJECT', '${escape ["'" "\\"] cfg.email.digestSubject}'); |
||||
''; |
||||
|
||||
in { |
||||
|
||||
###### interface |
||||
|
||||
options = { |
||||
|
||||
services.tt-rss = { |
||||
|
||||
enable = mkEnableOption "tt-rss"; |
||||
|
||||
user = mkOption { |
||||
type = types.str; |
||||
default = "nginx"; |
||||
example = "nginx"; |
||||
description = '' |
||||
User account under which both the service and the web-application run. |
||||
''; |
||||
}; |
||||
|
||||
pool = mkOption { |
||||
type = types.str; |
||||
default = "${poolName}"; |
||||
description = '' |
||||
Name of existing phpfpm pool that is used to run web-application. |
||||
If not specified a pool will be created automatically with |
||||
default values. |
||||
''; |
||||
}; |
||||
|
||||
# TODO: Re-enable after https://github.com/NixOS/nixpkgs/pull/15862 is merged |
||||
|
||||
# virtualHost = mkOption { |
||||
# type = types.str; |
||||
# default = "${virtualHostName}"; |
||||
# description = '' |
||||
# Name of existing nginx virtual host that is used to run web-application. |
||||
# If not specified a host will be created automatically with |
||||
# default values. |
||||
# ''; |
||||
# }; |
||||
|
||||
database = { |
||||
type = mkOption { |
||||
type = types.enum ["pgsql" "mysql"]; |
||||
default = "pgsql"; |
||||
description = '' |
||||
Database to store feeds. Supported are pgsql and mysql. |
||||
''; |
||||
}; |
||||
|
||||
host = mkOption { |
||||
type = types.str; |
||||
default = "localhost"; |
||||
description = '' |
||||
Host of the database. |
||||
''; |
||||
}; |
||||
|
||||
name = mkOption { |
||||
type = types.str; |
||||
default = "tt_rss"; |
||||
description = '' |
||||
Name of the existing database. |
||||
''; |
||||
}; |
||||
|
||||
user = mkOption { |
||||
type = types.str; |
||||
default = "tt_rss"; |
||||
description = '' |
||||
The database user. The user must exist and has access to |
||||
the specified database. |
||||
''; |
||||
}; |
||||
|
||||
password = mkOption { |
||||
type = types.nullOr types.str; |
||||
default = null; |
||||
description = '' |
||||
The database user's password. |
||||
''; |
||||
}; |
||||
|
||||
port = mkOption { |
||||
type = types.nullOr types.int; |
||||
default = null; |
||||
description = '' |
||||
The database's port. If not set, the default ports will be provided (5432 |
||||
and 3306 for pgsql and mysql respectively). |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
auth = { |
||||
autoCreate = mkOption { |
||||
type = types.bool; |
||||
default = true; |
||||
description = '' |
||||
Allow authentication modules to auto-create users in tt-rss internal |
||||
database when authenticated successfully. |
||||
''; |
||||
}; |
||||
|
||||
autoLogin = mkOption { |
||||
type = types.bool; |
||||
default = true; |
||||
description = '' |
||||
Automatically login user on remote or other kind of externally supplied |
||||
authentication, otherwise redirect to login form as normal. |
||||
If set to true, users won't be able to set application language |
||||
and settings profile. |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
pubSubHubbub = { |
||||
hub = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
URL to a PubSubHubbub-compatible hub server. If defined, "Published |
||||
articles" generated feed would automatically become PUSH-enabled. |
||||
''; |
||||
}; |
||||
|
||||
enable = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = '' |
||||
Enable client PubSubHubbub support in tt-rss. When disabled, tt-rss |
||||
won't try to subscribe to PUSH feed updates. |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
sphinx = { |
||||
server = mkOption { |
||||
type = types.str; |
||||
default = "localhost:9312"; |
||||
description = '' |
||||
Hostname:port combination for the Sphinx server. |
||||
''; |
||||
}; |
||||
|
||||
index = mkOption { |
||||
type = types.listOf types.str; |
||||
default = ["ttrss" "delta"]; |
||||
description = '' |
||||
Index names in Sphinx configuration. Example configuration |
||||
files are available on tt-rss wiki. |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
registration = { |
||||
enable = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = '' |
||||
Allow users to register themselves. Please be aware that allowing |
||||
random people to access your tt-rss installation is a security risk |
||||
and potentially might lead to data loss or server exploit. Disabled |
||||
by default. |
||||
''; |
||||
}; |
||||
|
||||
notifyAddress = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
Email address to send new user notifications to. |
||||
''; |
||||
}; |
||||
|
||||
maxUsers = mkOption { |
||||
type = types.int; |
||||
default = 0; |
||||
description = '' |
||||
Maximum amount of users which will be allowed to register on this |
||||
system. 0 - no limit. |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
email = { |
||||
server = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
example = "localhost:25"; |
||||
description = '' |
||||
Hostname:port combination to send outgoing mail. Blank - use system |
||||
MTA. |
||||
''; |
||||
}; |
||||
|
||||
login = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
SMTP authentication login used when sending outgoing mail. |
||||
''; |
||||
}; |
||||
|
||||
password = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
SMTP authentication password used when sending outgoing mail. |
||||
''; |
||||
}; |
||||
|
||||
security = mkOption { |
||||
type = types.enum ["" "ssl" "tls"]; |
||||
default = ""; |
||||
description = '' |
||||
Used to select a secure SMTP connection. Allowed values: ssl, tls, |
||||
or empty. |
||||
''; |
||||
}; |
||||
|
||||
fromName = mkOption { |
||||
type = types.str; |
||||
default = "Tiny Tiny RSS"; |
||||
description = '' |
||||
Name for sending outgoing mail. This applies to password reset |
||||
notifications, digest emails and any other mail. |
||||
''; |
||||
}; |
||||
|
||||
fromAddress = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
Address for sending outgoing mail. This applies to password reset |
||||
notifications, digest emails and any other mail. |
||||
''; |
||||
}; |
||||
|
||||
digestSubject = mkOption { |
||||
type = types.str; |
||||
default = "[tt-rss] New headlines for last 24 hours"; |
||||
description = '' |
||||
Subject line for email digests. |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
sessionCookieLifetime = mkOption { |
||||
type = types.int; |
||||
default = 86400; |
||||
description = '' |
||||
Default lifetime of a session (e.g. login) cookie. In seconds, |
||||
0 means cookie will be deleted when browser closes. |
||||
''; |
||||
}; |
||||
|
||||
selfUrlPath = mkOption { |
||||
type = types.str; |
||||
description = '' |
||||
Full URL of your tt-rss installation. This should be set to the |
||||
location of tt-rss directory, e.g. http://example.org/tt-rss/ |
||||
You need to set this option correctly otherwise several features |
||||
including PUSH, bookmarklets and browser integration will not work properly. |
||||
''; |
||||
example = "http://localhost"; |
||||
}; |
||||
|
||||
feedCryptKey = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
Key used for encryption of passwords for password-protected feeds |
||||
in the database. A string of 24 random characters. If left blank, encryption |
||||
is not used. Requires mcrypt functions. |
||||
Warning: changing this key will make your stored feed passwords impossible |
||||
to decrypt. |
||||
''; |
||||
}; |
||||
|
||||
singleUserMode = mkOption { |
||||
type = types.bool; |
||||
default = true; |
||||
|
||||
description = '' |
||||
Operate in single user mode, disables all functionality related to |
||||
multiple users and authentication. Enabling this assumes you have |
||||
your tt-rss directory protected by other means (e.g. http auth). |
||||
''; |
||||
}; |
||||
|
||||
simpleUpdateMode = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = '' |
||||
Enables fallback update mode where tt-rss tries to update feeds in |
||||
background while tt-rss is open in your browser. |
||||
If you don't have a lot of feeds and don't want to or can't run |
||||
background processes while not running tt-rss, this method is generally |
||||
viable to keep your feeds up to date. |
||||
Still, there are more robust (and recommended) updating methods |
||||
available, you can read about them here: http://tt-rss.org/wiki/UpdatingFeeds |
||||
''; |
||||
}; |
||||
|
||||
forceArticlePurge = mkOption { |
||||
type = types.int; |
||||
default = 0; |
||||
description = '' |
||||
When this option is not 0, users ability to control feed purging |
||||
intervals is disabled and all articles (which are not starred) |
||||
older than this amount of days are purged. |
||||
''; |
||||
}; |
||||
|
||||
checkForUpdates = mkOption { |
||||
type = types.bool; |
||||
default = true; |
||||
description = '' |
||||
Check for updates automatically if running Git version |
||||
''; |
||||
}; |
||||
|
||||
enableGZipOutput = mkOption { |
||||
type = types.bool; |
||||
default = true; |
||||
description = '' |
||||
Selectively gzip output to improve wire performance. This requires |
||||
PHP Zlib extension on the server. |
||||
Enabling this can break tt-rss in several httpd/php configurations, |
||||
if you experience weird errors and tt-rss failing to start, blank pages |
||||
after login, or content encoding errors, disable it. |
||||
''; |
||||
}; |
||||
|
||||
plugins = mkOption { |
||||
type = types.listOf types.str; |
||||
default = ["auth_internal" "note"]; |
||||
description = '' |
||||
List of plugins to load automatically for all users. |
||||
System plugins have to be specified here. Please enable at least one |
||||
authentication plugin here (auth_*). |
||||
Users may enable other user plugins from Preferences/Plugins but may not |
||||
disable plugins specified in this list. |
||||
Disabling auth_internal in this list would automatically disable |
||||
reset password link on the login form. |
||||
''; |
||||
}; |
||||
|
||||
logDestination = mkOption { |
||||
type = types.enum ["" "sql" "syslog"]; |
||||
default = "sql"; |
||||
description = '' |
||||
Log destination to use. Possible values: sql (uses internal logging |
||||
you can read in Preferences -> System), syslog - logs to system log. |
||||
Setting this to blank uses PHP logging (usually to http server |
||||
error.log). |
||||
''; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
|
||||
###### implementation |
||||
|
||||
config = let |
||||
root = "/var/lib/tt-rss"; |
||||
in mkIf cfg.enable { |
||||
|
||||
services.phpfpm.pools = if cfg.pool == "${poolName}" then { |
||||
"${poolName}" = { |
||||
listen = "/var/run/phpfpm/${poolName}.sock"; |
||||
extraConfig = '' |
||||
listen.owner = nginx |
||||
listen.group = nginx |
||||
listen.mode = 0600 |
||||
user = nginx |
||||
pm = dynamic |
||||
pm.max_children = 75 |
||||
pm.start_servers = 10 |
||||
pm.min_spare_servers = 5 |
||||
pm.max_spare_servers = 20 |
||||
pm.max_requests = 500 |
||||
catch_workers_output = 1 |
||||
''; |
||||
}; |
||||
} else {}; |
||||
|
||||
# TODO: Re-enable after https://github.com/NixOS/nixpkgs/pull/15862 is merged |
||||
|
||||
# services.nginx.virtualHosts = if cfg.virtualHost == "${virtualHostName}" then { |
||||
# "${virtualHostName}" = { |
||||
# root = "${root}"; |
||||
# extraConfig = '' |
||||
# access_log /var/log/nginx-${virtualHostName}-access.log; |
||||
# error_log /var/log/nginx-${virtualHostName}-error.log; |
||||
# ''; |
||||
|
||||
# locations."/" = { |
||||
# extraConfig = '' |
||||
# index index.php; |
||||
# ''; |
||||
# }; |
||||
|
||||
# locations."~ \.php$" = { |
||||
# extraConfig = '' |
||||
# fastcgi_split_path_info ^(.+\.php)(/.+)$; |
||||
# fastcgi_pass unix:${config.services.phpfpm.pools."${cfg.pool}".listen}; |
||||
# fastcgi_index index.php; |
||||
# fastcgi_param SCRIPT_FILENAME ${root}/$fastcgi_script_name; |
||||
|
||||
# include ${pkgs.nginx}/conf/fastcgi_params; |
||||
# ''; |
||||
# }; |
||||
# }; |
||||
# } else {}; |
||||
|
||||
|
||||
systemd.services.tt-rss = let |
||||
dbService = if cfg.database.type == "pgsql" then "postgresql.service" else "mysql.service"; |
||||
in { |
||||
|
||||
description = "Tiny Tiny RSS feeds update daemon"; |
||||
|
||||
preStart = let |
||||
callSql = if cfg.database.type == "pgsql" then (e: '' |
||||
${optionalString (cfg.database.password != null) |
||||
"PGPASSWORD=${cfg.database.password}"} ${pkgs.postgresql95}/bin/psql \ |
||||
-U ${cfg.database.user} \ |
||||
-h ${cfg.database.host} \ |
||||
--port ${toString dbPort} \ |
||||
-c '${e}' \ |
||||
${cfg.database.name}'') |
||||
|
||||
else if cfg.database.type == "mysql" then (e: '' |
||||
echo '${e}' | ${pkgs.mysql}/bin/mysql \ |
||||
${optionalString (cfg.database.password != null) |
||||
"-p${cfg.database.password}"} \ |
||||
-u ${cfg.database.user} \ |
||||
-h ${cfg.database.host} \ |
||||
-P ${toString dbPort} \ |
||||
${cfg.database.name}'') |
||||
|
||||
else ""; |
||||
|
||||
in '' |
||||
rm -rf "${root}/*" |
||||
mkdir -m 755 -p "${root}" |
||||
cp -r "${pkgs.tt-rss}/"* "${root}" |
||||
ln -sf "${tt-rss-config}" "${root}/config.php" |
||||
chown -R "${cfg.user}" "${root}" |
||||
chmod -R 755 "${root}" |
||||
'' + (optionalString (cfg.database.type == "pgsql") '' |
||||
|
||||
exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \ |
||||
| tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//') |
||||
|
||||
if [ "$exists" == 'f' ]; then |
||||
${callSql "\\i ${pkgs.tt-rss}/schema/ttrss_schema_${cfg.database.type}.sql"} |
||||
else |
||||
echo 'The database contains some data. Leaving it as it is.' |
||||
fi; |
||||
'') + (optionalString (cfg.database.type == "mysql") '' |
||||
|
||||
exists=$(${callSql "select count(*) > 0 from information_schema.tables where table_schema = schema()"} \ |
||||
| tail -n+2 | sed -e 's/[ \n\t]*//') |
||||
|
||||
if [ "$exists" == '0' ]; then |
||||
${callSql "\\. ${pkgs.tt-rss}/schema/ttrss_schema_${cfg.database.type}.sql"} |
||||
else |
||||
echo 'The database contains some data. Leaving it as it is.' |
||||
fi; |
||||
''); |
||||
|
||||
serviceConfig = { |
||||
User = "${cfg.user}"; |
||||
ExecStart = "${pkgs.php}/bin/php /var/lib/tt-rss/update.php --daemon"; |
||||
StandardOutput = "syslog"; |
||||
StandardError = "syslog"; |
||||
PermissionsStartOnly = true; |
||||
}; |
||||
|
||||
wantedBy = [ "multi-user.target" ]; |
||||
requires = ["${dbService}"]; |
||||
after = ["network.target" "${dbService}"]; |
||||
}; |
||||
}; |
||||
} |
@ -0,0 +1,35 @@ |
||||
{ lib }: |
||||
|
||||
with lib; { |
||||
|
||||
options = { |
||||
|
||||
listen = mkOption { |
||||
type = types.str; |
||||
example = "/path/to/unix/socket"; |
||||
description = '' |
||||
The address on which to accept FastCGI requests. |
||||
''; |
||||
}; |
||||
|
||||
extraConfig = mkOption { |
||||
type = types.lines; |
||||
example = '' |
||||
user = nobody |
||||
pm = dynamic |
||||
pm.max_children = 75 |
||||
pm.start_servers = 10 |
||||
pm.min_spare_servers = 5 |
||||
pm.max_spare_servers = 20 |
||||
pm.max_requests = 500 |
||||
''; |
||||
|
||||
description = '' |
||||
Extra lines that go into the pool configuration. |
||||
See the documentation on <literal>php-fpm.conf</literal> for |
||||
details on configuration directives. |
||||
''; |
||||
}; |
||||
}; |
||||
} |
||||
|
@ -0,0 +1,34 @@ |
||||
# verifies: |
||||
# 1. GoCD agent starts |
||||
# 2. GoCD agent responds |
||||
# 3. GoCD agent is available on GoCD server using GoCD API |
||||
# 3.1. https://api.go.cd/current/#get-all-agents |
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : { |
||||
name = "gocd-agent"; |
||||
meta = with pkgs.stdenv.lib.maintainers; { |
||||
maintainers = [ swarren83 ]; |
||||
}; |
||||
|
||||
nodes = { |
||||
gocd_agent = |
||||
{ config, pkgs, ... }: |
||||
{ |
||||
virtualisation.memorySize = 2048; |
||||
services.gocd-agent = { |
||||
enable = true; |
||||
}; |
||||
services.gocd-server = { |
||||
enable = true; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
testScript = '' |
||||
startAll; |
||||
$gocd_agent->waitForUnit("gocd-server"); |
||||
$gocd_agent->waitForOpenPort("8153"); |
||||
$gocd_agent->waitForUnit("gocd-agent"); |
||||
$gocd_agent->waitUntilSucceeds("curl -s -f localhost:8153/go/api/agents -H 'Accept: application/vnd.go.cd.v2+json'"); |
||||
''; |
||||
}) |
@ -0,0 +1,28 @@ |
||||
# verifies: |
||||
# 1. GoCD server starts |
||||
# 2. GoCD server responds |
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : |
||||
|
||||
{ |
||||
name = "gocd-server"; |
||||
meta = with pkgs.stdenv.lib.maintainers; { |
||||
maintainers = [ swarren83 ]; |
||||
}; |
||||
|
||||
nodes = { |
||||
gocd_server = |
||||
{ config, pkgs, ... }: |
||||
{ |
||||
virtualisation.memorySize = 2048; |
||||
services.gocd-server.enable = true; |
||||
}; |
||||
}; |
||||
|
||||
testScript = '' |
||||
$gocd_server->start; |
||||
$gocd_server->waitForUnit("gocd-server"); |
||||
$gocd_server->waitForOpenPort("8153"); |
||||
$gocd_server->waitUntilSucceeds("curl -s -f localhost:8153/go"); |
||||
''; |
||||
}) |
@ -0,0 +1,22 @@ |
||||
{ stdenv, fetchurl, pkgconfig, openexr, libpng12, libjpeg }: |
||||
|
||||
stdenv.mkDerivation rec { |
||||
name = "exrtools"; |
||||
version = "0.4"; |
||||
|
||||
src = fetchurl { |
||||
url = "http://scanline.ca/exrtools/${name}-${version}.tar.gz"; |
||||
sha256 = "0jpkskqs1yjiighab4s91jy0c0qxcscwadfn94xy2mm2bx2qwp4z"; |
||||
}; |
||||
|
||||
buildInputs = [ stdenv pkgconfig openexr libpng12 libjpeg ]; |
||||
|
||||
meta = with stdenv.lib; { |
||||
description = "Collection of utilities for manipulating OpenEXR images"; |
||||
homepage = "http://scanline.ca/exrtools"; |
||||
platforms = platforms.linux; |
||||
license = licenses.mit; |
||||
maintainers = [ maintainers.juliendehos ]; |
||||
}; |
||||
} |
||||
|
@ -1,31 +0,0 @@ |
||||
# Description: Fix lighthouse Makefile
|
||||
Index: Makefile
|
||||
===================================================================
|
||||
--- ./Makefile 1970-01-01 02:00:01.000000000 +0200
|
||||
+++ ./Makefile 1970-01-01 02:00:01.000000000 +0200
|
||||
@@ -19,21 +19,10 @@
|
||||
endif
|
||||
|
||||
# Library specific
|
||||
-HAS_GDK := $(shell pkg-config --exists gdk-2.0 echo $?)
|
||||
-ifdef $(HAS_GDK)
|
||||
- CFLAGS+=`pkg-config --cflags gdk-2.0`
|
||||
- LDFLAGS+=`pkg-config --libs gdk-2.0`
|
||||
-else
|
||||
- CFLAGS+=-DNO_GDK
|
||||
-endif
|
||||
-HAS_PANGO := $(shell pkg-config --exists pango echo $?)
|
||||
-ifdef $(HAS_PANGO)
|
||||
- CFLAGS+=`pkg-config --cflags pango`
|
||||
- LDFLAGS+=`pkg-config --libs pango`
|
||||
-else
|
||||
- CFLAGS+=-DNO_PANGO
|
||||
-endif
|
||||
-
|
||||
+CFLAGS+=$(shell pkg-config --cflags gdk-2.0)
|
||||
+LDFLAGS+=$(shell pkg-config --libs gdk-2.0)
|
||||
+CFLAGS+=$(shell pkg-config --cflags pango)
|
||||
+LDFLAGS+=$(shell pkg-config --libs pango)
|
||||
|
||||
all: lighthouse
|
||||
|
@ -0,0 +1,43 @@ |
||||
{ stdenv, fetchgit, makeWrapper, gettext |
||||
, python27, python2Packages |
||||
}: |
||||
|
||||
stdenv.mkDerivation rec { |
||||
name = "metamorphose2-${version}"; |
||||
version = "0.9.0beta"; |
||||
|
||||
# exif-py vendored via submodule |
||||
# mutagen vendored via copy |
||||
src = fetchgit { |
||||
url = "https://github.com/metamorphose/metamorphose2.git"; |
||||
#rev = "refs/tags/v2.${version}"; #for when wxPython3 support is released |
||||
rev = "d2bdd6a86340b9668e93b35a6a568894c9909d68"; |
||||
sha256 = "0ivcb3c8hidrff0ivl4dnwa2p3ihpqjdbvdig8dhg9mm5phdbabn"; |
||||
}; |
||||
|
||||
postPatch = '' |
||||
substituteInPlace messages/Makefile \ |
||||
--replace "\$(shell which msgfmt)" "${gettext}/bin/msgfmt" |
||||
''; |
||||
|
||||
postInstall = '' |
||||
rm $out/bin/metamorphose2 |
||||
makeWrapper ${python27}/bin/python $out/bin/metamorphose2 \ |
||||
--prefix PYTHONPATH : $PYTHONPATH:$(toPythonPath "$out") \ |
||||
--add-flags "-O $out/share/metamorphose2/metamorphose2.py -w=3" |
||||
''; |
||||
|
||||
buildInput = [ gettext python27 ]; |
||||
nativeBuildInputs = [ makeWrapper ]; |
||||
propagatedBuildInputs = [ python2Packages.wxPython python2Packages.pillow ]; |
||||
|
||||
makeFlags = [ "PREFIX=$(out)" ]; |
||||
|
||||
meta = with stdenv.lib; { |
||||
description = "a graphical mass renaming program for files and folders"; |
||||
homepage = "https://github.com/metamorphose/metamorphose2"; |
||||
license = with licenses; gpl3Plus; |
||||
maintainer = with maintainers; [ ramkromberg ]; |
||||
platforms = with platforms; linux; |
||||
}; |
||||
} |
@ -1,49 +1,60 @@ |
||||
{ stdenv, fetchurl, pkgconfig, intltool, itstool, makeWrapper |
||||
{ stdenv, fetchurl, pkgconfig, intltool, itstool, wrapGAppsHook |
||||
, python3Packages, gst, gtk3, hicolor_icon_theme |
||||
, gobjectIntrospection, librsvg, gnome3, libnotify |
||||
# for gst-transcoder: |
||||
, which, meson, ninja |
||||
}: |
||||
|
||||
let |
||||
version = "0.95"; |
||||
version = "0.96"; |
||||
|
||||
# gst-transcoder will eventually be merged with gstreamer (according to |
||||
# gst-transcoder 1.8.0 release notes). For now the only user is pitivi so we |
||||
# don't bother exposing the package to all of nixpkgs. |
||||
gst-transcoder = stdenv.mkDerivation rec { |
||||
name = "gst-transcoder-1.8.0"; |
||||
src = fetchurl { |
||||
name = "${name}.tar.gz"; |
||||
url = "https://github.com/pitivi/gst-transcoder/archive/1.8.0.tar.gz"; |
||||
sha256 = "0iggr6idmp7cmfsf6pkhfl3jq1bkga37jl5prbcl1zapkzi26fg6"; |
||||
}; |
||||
buildInputs = [ which meson ninja pkgconfig gobjectIntrospection ] |
||||
++ (with gst; [ gstreamer gst-plugins-base ]); |
||||
}; |
||||
|
||||
in stdenv.mkDerivation rec { |
||||
name = "pitivi-${version}"; |
||||
|
||||
src = fetchurl { |
||||
url = "mirror://gnome/sources/pitivi/${version}/${name}.tar.xz"; |
||||
sha256 = "04ykw619aikhxk5wj7z44pvwl52053d1kamcxpscw0ixrh5j45az"; |
||||
}; |
||||
|
||||
meta = with stdenv.lib; { |
||||
description = "Non-Linear video editor utilizing the power of GStreamer"; |
||||
homepage = "http://pitivi.org/"; |
||||
longDescription = '' |
||||
Pitivi is a video editor built upon the GStreamer Editing Services. |
||||
It aims to be an intuitive and flexible application |
||||
that can appeal to newbies and professionals alike. |
||||
''; |
||||
license = licenses.lgpl21Plus; |
||||
platforms = platforms.linux; |
||||
sha256 = "115d37mvi32yds8gqj2yidkk6pap7szavhjf2hw0388ynydlc2zs"; |
||||
}; |
||||
|
||||
nativeBuildInputs = [ pkgconfig intltool itstool makeWrapper ]; |
||||
nativeBuildInputs = [ pkgconfig intltool itstool wrapGAppsHook ]; |
||||
|
||||
buildInputs = [ |
||||
gobjectIntrospection gtk3 librsvg gnome3.gnome_desktop |
||||
gnome3.defaultIconTheme |
||||
gnome3.gsettings_desktop_schemas libnotify |
||||
gst-transcoder |
||||
] ++ (with gst; [ |
||||
gstreamer gst-editing-services |
||||
gst-plugins-base gst-plugins-good |
||||
gst-plugins-bad gst-plugins-ugly gst-libav gst-validate |
||||
]) ++ (with python3Packages; [ |
||||
python pygobject3 gst-python pyxdg numpy pycairo sqlite3 matplotlib |
||||
dbus |
||||
]); |
||||
|
||||
preFixup = '' |
||||
wrapProgram "$out/bin/pitivi" \ |
||||
--set GDK_PIXBUF_MODULE_FILE "$GDK_PIXBUF_MODULE_FILE" \ |
||||
--prefix GI_TYPELIB_PATH : "$GI_TYPELIB_PATH" \ |
||||
--prefix GST_PLUGIN_SYSTEM_PATH_1_0 : "$GST_PLUGIN_SYSTEM_PATH_1_0" \ |
||||
--prefix XDG_DATA_DIRS : "$XDG_ICON_DIRS:$out/share:$GSETTINGS_SCHEMAS_PATH" |
||||
''; |
||||
meta = with stdenv.lib; { |
||||
description = "Non-Linear video editor utilizing the power of GStreamer"; |
||||
homepage = "http://pitivi.org/"; |
||||
longDescription = '' |
||||
Pitivi is a video editor built upon the GStreamer Editing Services. |
||||
It aims to be an intuitive and flexible application |
||||
that can appeal to newbies and professionals alike. |
||||
''; |
||||
license = licenses.lgpl21Plus; |
||||
platforms = platforms.linux; |
||||
}; |
||||
} |
||||
|
@ -0,0 +1,35 @@ |
||||
{ stdenv, fetchurl, libX11, libXext, libXrandr, libXrender, |
||||
xproto, xextproto, randrproto, renderproto, kbproto, patches ? [] }: |
||||
|
||||
stdenv.mkDerivation rec { |
||||
name = "evilwm-1.1.1"; |
||||
|
||||
src = fetchurl { |
||||
url = "http://www.6809.org.uk/evilwm/${name}.tar.gz"; |
||||
sha256 = "79589c296a5915ee0bae1d231e8912601fc794d9f0a9cacb6b648ff9a5f2602a"; |
||||
}; |
||||
|
||||
buildInputs = [ libX11 libXext libXrandr libXrender |
||||
xproto xextproto randrproto renderproto kbproto ]; |
||||
|
||||
prePatch = ''substituteInPlace ./Makefile --replace /usr $out \ |
||||
--replace "CC = gcc" "#CC = gcc"''; |
||||
|
||||
# Allow users set their own list of patches |
||||
inherit patches; |
||||
|
||||
meta = with stdenv.lib; { |
||||
homepage = "http://www.6809.org.uk/evilwm/"; |
||||
description = "Minimalist window manager for the X Window System"; |
||||
|
||||
license = { |
||||
shortName = "evilwm"; |
||||
fullName = "Custom, inherited from aewm and 9wm"; |
||||
url = http://www.6809.org.uk/evilwm/; |
||||
free = true; |
||||
}; # like BSD/MIT, but Share-Alike'y; See README. |
||||
|
||||
maintainers = with maintainers; [ amiloradovsky ]; |
||||
platforms = platforms.all; |
||||
}; |
||||
} |
@ -0,0 +1,24 @@ |
||||
{ fetchFromGitHub, stdenv }: |
||||
|
||||
stdenv.mkDerivation rec { |
||||
name = "i3blocks-gaps-${version}"; |
||||
version = "1.4"; |
||||
|
||||
src = fetchFromGitHub { |
||||
owner = "Airblader"; |
||||
repo = "i3blocks-gaps"; |
||||
rev = "4cfdf93c75f729a2c96d471004d31734e923812f"; |
||||
sha256 = "0v9307ij8xzwdaxay3r75sd2cp453s3qb6q7dy9fks2p6wwqpazi"; |
||||
}; |
||||
|
||||
makeFlags = "all"; |
||||
installFlags = "PREFIX=\${out} VERSION=${version}"; |
||||
|
||||
meta = with stdenv.lib; { |
||||
description = "A flexible scheduler for your i3bar blocks -- this is a fork to use with i3-gaps"; |
||||
homepage = https://github.com/Airblader/i3blocks-gaps; |
||||
license = licenses.gpl3; |
||||
maintainers = [ "carlsverre" ]; |
||||
platforms = platforms.all; |
||||
}; |
||||
} |
@ -1,31 +0,0 @@ |
||||
args @ { fetchurl, stdenv, builderDefs, paths, mkfontdir, mkfontscale }: |
||||
with args; |
||||
let localDefs = builderDefs.passthru.function { |
||||
src =""; /* put a fetchurl here */ |
||||
buildInputs = [mkfontdir mkfontscale]; |
||||
configureFlags = []; |
||||
}; |
||||
in with localDefs; |
||||
let |
||||
doInstall = fullDepEntry (" |
||||
mkdir -p \$out/share/fonts/ |
||||
cd \$out/share/fonts |
||||
for i in ${toString paths}; do |
||||
find \$i -type f -exec ln -s '{}' . ';' ; |
||||
done |
||||
mkfontdir |
||||
mkfontscale |
||||
") [minInit addInputs defEnsureDir] ; |
||||
in |
||||
stdenv.mkDerivation rec { |
||||
name = "wrapped-font-dir"; |
||||
builder = writeScript (name + "-builder") |
||||
(textClosure localDefs [ doInstall doForceShare doPropagate]); |
||||
preferLocalBuild = true; |
||||
meta = { |
||||
description = " |
||||
Just a wrapper to create fonts.dir and fonts.scale . |
||||
"; |
||||
inherit src; |
||||
}; |
||||
} |
@ -1,39 +1,41 @@ |
||||
{ stdenv, fetchurl, wrapFonts }: |
||||
{ stdenv, fetchurl, mkfontdir, mkfontscale }: |
||||
|
||||
let |
||||
stdenv.mkDerivation rec { |
||||
name = "ucs-fonts-${version}"; |
||||
version = "20090406"; |
||||
|
||||
srcA = fetchurl { |
||||
url = http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz; |
||||
sha256 = "12hgizg25fzmk10wjl0c88x97h3pg5r9ga122s3y28wixz6x2bvh"; |
||||
}; |
||||
|
||||
srcB = fetchurl { |
||||
url = http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts-asian.tar.gz; |
||||
sha256 = "0ibjy4xpz5j373hsdr8bx99czfpclqmviwwv768j8n7z12z3wa51"; |
||||
}; |
||||
|
||||
srcC = fetchurl { |
||||
url = http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts-75dpi100dpi.tar.gz; |
||||
sha256 = "08vqr8yb636xa1s28vf3pm22dzkia0gisvsi2svqjqh4kk290pzh"; |
||||
}; |
||||
srcs = [ |
||||
(fetchurl { |
||||
url = http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz; |
||||
sha256 = "12hgizg25fzmk10wjl0c88x97h3pg5r9ga122s3y28wixz6x2bvh"; |
||||
}) |
||||
(fetchurl { |
||||
url = http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts-asian.tar.gz; |
||||
sha256 = "0ibjy4xpz5j373hsdr8bx99czfpclqmviwwv768j8n7z12z3wa51"; |
||||
}) |
||||
(fetchurl { |
||||
url = http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts-75dpi100dpi.tar.gz; |
||||
sha256 = "08vqr8yb636xa1s28vf3pm22dzkia0gisvsi2svqjqh4kk290pzh"; |
||||
}) |
||||
]; |
||||
|
||||
sourceRoot = "."; |
||||
|
||||
buildInputs = [ mkfontdir mkfontscale ]; |
||||
|
||||
in |
||||
phases = [ "unpackPhase" "installPhase" ]; |
||||
|
||||
wrapFonts (stdenv.mkDerivation { |
||||
name = "ucs-fonts"; |
||||
|
||||
phases = ["installPhase"]; |
||||
|
||||
installPhase = '' |
||||
tar xf ${srcA} |
||||
tar xf ${srcB} |
||||
tar xf ${srcC} |
||||
mkdir -p $out/share/fonts/ucs-fonts |
||||
cp *.bdf $out/share/fonts/ucs-fonts |
||||
mkdir -p $out/share/fonts |
||||
cp *.bdf $out/share/fonts |
||||
cd $out/share/fonts |
||||
mkfontdir |
||||
mkfontscale |
||||
''; |
||||
|
||||
meta = { |
||||
meta = with stdenv.lib; { |
||||
description = "Unicode bitmap fonts"; |
||||
maintainers = [stdenv.lib.maintainers.raskin]; |
||||
maintainers = [ maintainers.raskin ]; |
||||
platforms = platforms.all; |
||||
}; |
||||
}) |
||||
} |
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue