1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
About
=====
Nixsap is a set of modules built on top of
[NixOS](https://nixos.org/)/[Nixpkgs](https://nixos.org/nixpkgs/). Nixsap
provides NixOS modules in the `nixsap` "namespace", e. g. `nixsap.apps.mariadb`
or `nixsap.system.users`, and adds or overrides some packages in Nixpkgs.
From vanila Nixpkgs, Nixsap relies only on basic services like systemd, ssh, ntpd
and package set (extending and overriding it).
Features
========
Plug & Play
-----------
Each module under the [modules](./modules) directory is automatically available.
When creating a new machine just use
imports = [ <nixsap> ];
Each package `foo` under the [modules/pkgs](./modules/pkgs) is automatically available as `pkgs.foo`.
For example:
modules/pkgs/writeXML.nix => pkgs.writeXML
modules/pkgs/rdsdump/default.nix => pkgs.rdsdump
You can use this techniques in your own projects. You can take out any modules
or packages and put them into your project with your modifications without
maintaning a fork of Nixsap. When taking modules you have to change the
`nixsap` namespace to something different to avoid conflicts.
It is also possible to build and install packages that are overridden
by Nixsap, for example:
```
nix-env [-I nixpkgs=/path/to/vanila/nixpkgs] -f /path/to/nixsap/pkgs -i nodejs-sass
```
Automatic unix user id
-----------------------
To create daemon users just add their names into the list
`nixsap.system.users.daemons`. List `nixsap.system.users.normal`
does the same for users with login shell, and `nixsap.system.groups`
for unix groups. Users and groups will automatically get their
ids based on their names in a deterministic manner. See examples
in the [applications directory](./modules/apps) and implementation in
[modules/system/users.nix](modules/system/users.nix). This feature is used
throughout `nixsap.apps`.
Examples:
# id icinga
uid=1240920351(icinga) gid=100(users) groups=21(proc),100(users)
# id pashev
uid=1141737888(pashev) gid=100(users) groups=100(users),21(proc),62(systemd-journal),1061782283(sysops)
# id jenkins-dumpoo
uid=1201814562(jenkins-dumpoo) gid=1201814562(jenkins-dumpoo) groups=96(keys),1201814562(jenkins-dumpoo)
# id mariadb
uid=1213117043(mariadb) gid=1213117043(mariadb) groups=96(keys),1213117043(mariadb)
Keyrings
--------
[Keyrings](modules/deployment/keyrings.nix) provide a means of
deploying secret files with sensitive content. It's inspired by
[NixOps](https://nixos.org/nixops/) and relies on it as on reference
implementation. Most applications from `nixsap.apps` recognize keys from their
parameters or extract them from configuration files and automatically build
their keyrings.
Multi-instance applications
---------------------------
For most [applications](./modules/apps) it is possible to run multiple
instances of them on the same machine. Each instance may have its own
home directory and user. For example `jenkins-foo` with home directory
`/jenkins/foo` and user `jenkins-foo`. Not all applications allow that
purely for historical reasons, and this will be fixed eventually.
Design
======
Static analysis
---------------
There are a handful of tools used thoughout the applications to ensure
correctness at build time: `writeBashScript`, `writeXML`, `writePHPFile`.
`writeBashScript` uses [shellcheck](https://www.shellcheck.net/). `writeXML`
runs [xmllint](http://xmlsoft.org/xmllint.html). `writePHPFile` relies on
PHP's built-in syntax checker.
The objective it to do static analysis and linting for every single file
_at build time_. What is wanted: configuration files for Nginx, Icinga;
MySQL and PostgreSQL scripts, etc.
Parametrization
---------------
Everything that _can_ be used at build time should have a parameter (integer,
string, path, etc.). Examples are TCP port, data directory, UNIX user. TCP
port can be used for configuring firewall or HTTP proxy, data directory can
be used for setting up mount points, UNIX user can be included into extra
groups, etc. When we have it all parametrized we do not repeat ourselves.
Parametrization also helps modularity. I. e. you can define default set of
values and override only some of them in specific setups.
Some applications accept only discrete set of options, in that case we should
parametrize them all. Examples are memcached, php-fpm and sproxy2.
Parametrization should give access to all application features. Ideally,
parameters should exactly match to the application options, including
their names and meanings. Examples are MariaDB and PostgreSQL. This makes
documentation unnecessary, because each parameter is documented somewhere else.
Almost every parameter, if it's not required by application (i. e. has
a built-in default value), should have value `null` by default. If such
parameter is not set, it is not passed to the application. This is twofold:
more transparency because we use _application's_ defaults (not ours), and it
is safer to use different versions of application, when particular options
may be added or removed.
Even though, if the value of parameter is required at build time, the parameter
should have default value, preferably application's default. Example is
MariaDB's TCP port. We need it to configure firewall, thus we define it to
be 3306 by default.
If application default value is known to be insecure, we should set our own,
_secure_, default value.
Requirements
============
* [nixpkgs](https://nixos.org/nixpkgs/) >= 17.03
License
=======
This project is under the MIT license (see [LICENSE](LICENSE)),
unless stated otherwise in individual files.
|