diff --git a/.gitignore b/.gitignore index 165e92c7fc3..105e621d702 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ doc/NEWS.html doc/NEWS.txt doc/manual.html doc/manual.pdf +.version-suffix diff --git a/.version b/.version new file mode 100644 index 00000000000..381796ec8b7 --- /dev/null +++ b/.version @@ -0,0 +1 @@ +13.10 \ No newline at end of file diff --git a/VERSION b/VERSION deleted file mode 100644 index 9f8e9b69a33..00000000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.0 \ No newline at end of file diff --git a/doc/manual.xml b/doc/manual.xml index 927361ba5c8..d2c07859b28 100644 --- a/doc/manual.xml +++ b/doc/manual.xml @@ -5,7 +5,7 @@ Nixpkgs Manual - Draft (Version Draft (Version ) diff --git a/maintainers/docs/cross.txt b/doc/old/cross.txt similarity index 100% rename from maintainers/docs/cross.txt rename to doc/old/cross.txt diff --git a/maintainers/docs/update-upstream-data.txt b/doc/old/update-upstream-data.txt similarity index 100% rename from maintainers/docs/update-upstream-data.txt rename to doc/old/update-upstream-data.txt diff --git a/doc/package-notes.xml b/doc/package-notes.xml index 6dae036b338..8a35e640324 100644 --- a/doc/package-notes.xml +++ b/doc/package-notes.xml @@ -105,16 +105,6 @@ $ make menuconfig ARCH=arch - - Make sure that - CONFIG_FB_TILEBLITTING is not - set (otherwise fbsplash won't - work). This option has a tendency to be enabled as a - side-effect of other options. If it is, investigate why - (there's probably another option that forces it to be on) - and fix it. - - Copy .config over the new config file (e.g. config-2.6.22-i686-smp). @@ -137,22 +127,9 @@ $ make menuconfig ARCH=arch kernel modules and kernel-dependent packages listed in the kernelPackagesFor function in all-packages.nix (such as the NVIDIA drivers, - AUFS, splashutils, etc.). If the updated packages aren’t - backwards compatible with older kernels, you need to keep the - older versions and use some conditionals. For example, new - kernels require splashutils 1.5 while old kernel require 1.3, so - kernelPackagesFor says: - - -splashutils = - if kernel.features ? fbSplash then splashutils_13 else - if kernel.features ? fbConDecor then splashutils_15 else - null; - -splashutils_13 = ...; -splashutils_15 = ...; - - + AUFS, etc.). If the updated packages aren’t backwards compatible + with older kernels, you may need to keep the older versions + around. diff --git a/doc/quick-start.xml b/doc/quick-start.xml index a14de4077db..46578619e1f 100644 --- a/doc/quick-start.xml +++ b/doc/quick-start.xml @@ -71,7 +71,7 @@ $ git add pkgs/development/libraries/libfoo/default.nix GNU Multiple Precision arithmetic library (GMP): pkgs/development/libraries/gmp/default.nix. + xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/gmp/5.1.1.nix">pkgs/development/libraries/gmp/5.1.1.nix. Also done by the generic builder, but has a dependency on m4. @@ -86,7 +86,7 @@ $ git add pkgs/development/libraries/libfoo/default.nix Apache HTTPD: pkgs/servers/http/apache-httpd/default.nix. + xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/http/apache-httpd/2.4.nix">pkgs/servers/http/apache-httpd/2.4.nix. A bunch of optional features, variable substitutions in the configure flags, a post-install hook, and miscellaneous hackery. @@ -105,7 +105,7 @@ $ git add pkgs/development/libraries/libfoo/default.nix Thunderbird: pkgs/applications/networking/mailreaders/thunderbird/3.x.nix. + xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/mailreaders/thunderbird/default.nix">pkgs/applications/networking/mailreaders/thunderbird/default.nix. Lots of dependencies. diff --git a/pkgs/lib/attrsets.nix b/lib/attrsets.nix similarity index 97% rename from pkgs/lib/attrsets.nix rename to lib/attrsets.nix index 01d51779c80..7c93d8698de 100644 --- a/pkgs/lib/attrsets.nix +++ b/lib/attrsets.nix @@ -29,9 +29,8 @@ rec { ["x" "y"] applied with some value v returns `x.y = v;' */ setAttrByPath = attrPath: value: if attrPath == [] then value - else listToAttrs [( - nameValuePair (head attrPath) (setAttrByPath (tail attrPath) value) - )]; + else listToAttrs + [ { name = head attrPath; value = setAttrByPath (tail attrPath) value; } ]; getAttrFromPath = attrPath: set: @@ -133,7 +132,7 @@ rec { => { x = "x-foo"; y = "y-bar"; } */ mapAttrs = f: set: - listToAttrs (map (attr: nameValuePair attr (f attr (getAttr attr set))) (attrNames set)); + listToAttrs (map (attr: { name = attr; value = f attr (getAttr attr set); }) (attrNames set)); /* Like `mapAttrs', but allows the name of each attribute to be @@ -240,7 +239,7 @@ rec { # names, hopefully this does not affect the system because the maximal # laziness avoid computing twice the same expression and listToAttrs does # not care about duplicated attribute names. - zipAttrsWith = f: sets: zipWithNames (concatMap attrNames sets) f sets; + zipAttrsWith = f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets; zipAttrs = zipAttrsWith (name: values: values); diff --git a/pkgs/lib/composable-derivation.nix b/lib/composable-derivation.nix similarity index 100% rename from pkgs/lib/composable-derivation.nix rename to lib/composable-derivation.nix diff --git a/pkgs/lib/customisation.nix b/lib/customisation.nix similarity index 100% rename from pkgs/lib/customisation.nix rename to lib/customisation.nix diff --git a/pkgs/lib/debug.nix b/lib/debug.nix similarity index 100% rename from pkgs/lib/debug.nix rename to lib/debug.nix diff --git a/pkgs/lib/default.nix b/lib/default.nix similarity index 79% rename from pkgs/lib/default.nix rename to lib/default.nix index dea82ee077e..fc92e04503b 100644 --- a/pkgs/lib/default.nix +++ b/lib/default.nix @@ -8,7 +8,6 @@ let sources = import ./sources.nix; modules = import ./modules.nix; options = import ./options.nix; - properties = import ./properties.nix; types = import ./types.nix; meta = import ./meta.nix; debug = import ./debug.nix; @@ -21,11 +20,13 @@ let in { inherit trivial lists strings stringsWithDeps attrsets sources options - properties modules types meta debug maintainers licenses platforms systems; + modules types meta debug maintainers licenses platforms systems; + # Pull in some builtins not included elsewhere. + inherit (builtins) pathExists readFile; } # !!! don't include everything at top-level; perhaps only the most # commonly used functions. // trivial // lists // strings // stringsWithDeps // attrsets // sources - // properties // options // types // meta // debug // misc // modules + // options // types // meta // debug // misc // modules // systems // customisation diff --git a/pkgs/lib/licenses.nix b/lib/licenses.nix similarity index 94% rename from pkgs/lib/licenses.nix rename to lib/licenses.nix index c5c9133da6e..b13a72f3f64 100644 --- a/pkgs/lib/licenses.nix +++ b/lib/licenses.nix @@ -34,11 +34,9 @@ url = "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/AMD-ADL?revision=1.1"; }; - apsl20 = { - shortName = "APSL 2.0"; - fullName = "Apple Public Source License 2.0"; - url = http://opensource.org/licenses/APSL-2.0; - }; + # Apple Public Source License 2.0; + # http://opensource.org/licenses/APSL-2.0 + apsl20 = "APSL 2.0"; asl20 = { shortName = "ASL2.0"; @@ -96,11 +94,9 @@ url = http://www.mysql.com/about/legal/licensing/foss-exception; }; - gpl2Plus = { - shortName = "GPLv2+"; - fullName = "GNU General Public License version 2 or later"; - url = http://www.gnu.org/licenses/old-licenses/gpl-2.0.html; - }; + # GNU General Public License version 2 or later; + # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + gpl2Plus = "GPLv2+"; gpl3 = { shortName = "GPLv3"; @@ -190,6 +186,12 @@ url = http://www.mozilla.org/MPL/MPL-1.1.html; }; + mpl20 = { + shortName = "MPL2.0"; + fullName = "Mozilla Public License version 2.0"; + url = https://www.mozilla.org/MPL/2.0; + }; + openssl = { shortName = "openssl"; fullName = "OpenSSL license"; diff --git a/pkgs/lib/lists.nix b/lib/lists.nix similarity index 95% rename from pkgs/lib/lists.nix rename to lib/lists.nix index 578686ae366..d0b09539bf6 100644 --- a/pkgs/lib/lists.nix +++ b/lib/lists.nix @@ -1,14 +1,14 @@ # General list operations. let + inherit (import ./trivial.nix) deepSeq; inc = builtins.add 1; dec = n: builtins.sub n 1; - inherit (builtins) elemAt; in rec { - inherit (builtins) head tail length isList add sub lessThan; + inherit (builtins) head tail length isList add sub lessThan elemAt; # Create a list consisting of a single element. `singleton x' is @@ -118,6 +118,11 @@ in rec { all = pred: fold (x: y: if pred x then y else false) true; + # Count how many times function `pred' returns true for the elements + # of `list'. + count = pred: fold (x: c: if pred x then inc c else c) 0; + + # Return a singleton list or an empty list, depending on a boolean # value. Useful when building lists with optional elements # (e.g. `++ optional (system == "i686-linux") flashplayer'). @@ -165,10 +170,11 @@ in rec { zipLists = zipListsWith (fst: snd: { inherit fst snd; }); - - # Reverse the order of the elements of a list. + + # Reverse the order of the elements of a list. FIXME: O(n^2)! reverseList = fold (e: acc: acc ++ [ e ]) []; + # Sort a list based on a comparator function which compares two # elements and returns true if the first argument is strictly below # the second argument. The returned list is sorted in an increasing diff --git a/pkgs/lib/maintainers.nix b/lib/maintainers.nix similarity index 92% rename from pkgs/lib/maintainers.nix rename to lib/maintainers.nix index cd4242b170f..7f84e11e561 100644 --- a/pkgs/lib/maintainers.nix +++ b/lib/maintainers.nix @@ -5,6 +5,7 @@ alphabetically sorted. */ aforemny = "Alexander Foremny "; + algorith = "Dries Van Daele "; all = "Nix Committers "; amiddelk = "Arie Middelkoop "; amorsillo = "Andrew Morsillo "; @@ -19,6 +20,7 @@ bodil = "Bodil Stokke "; chaoflow = "Florian Friesdorf "; coconnor = "Corey O'Connor "; + coroa = "Jonas Hörsch "; edwtjo = "Edward Tjörnhammar "; eelco = "Eelco Dolstra "; ertes = "Ertugrul Söylemez "; @@ -41,6 +43,7 @@ phreedom = "Evgeny Egorochkin "; pierron = "Nicolas B. Pierron "; piotr = "Piotr Pietraszkiewicz "; + pSub = "Pascal Wittmann "; qknight = "Joachim Schiele "; raskin = "Michael Raskin <7c6f434c@mail.ru>"; rickynils = "Rickard Nilsson "; @@ -56,6 +59,8 @@ vcunat = "Vladimír Čunát "; viric = "Lluís Batlle i Rossell "; vizanto = "Danny Wilson "; + vlstill = "Vladimír Štill "; winden = "Antonio Vargas Gonzalez "; z77z = "Marco Maggesi "; + zef = "Zef Hemel "; } diff --git a/pkgs/lib/meta.nix b/lib/meta.nix similarity index 100% rename from pkgs/lib/meta.nix rename to lib/meta.nix diff --git a/pkgs/lib/misc.nix b/lib/misc.nix similarity index 99% rename from pkgs/lib/misc.nix rename to lib/misc.nix index 19e5081009d..c128b9af9d8 100644 --- a/pkgs/lib/misc.nix +++ b/lib/misc.nix @@ -206,9 +206,7 @@ rec { in work startSet [] []; - genericClosure = - if builtins ? genericClosure then builtins.genericClosure - else lazyGenericClosure; + genericClosure = builtins.genericClosure or lazyGenericClosure; innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else innerModifySumArgs f x (a // b); diff --git a/lib/modules.nix b/lib/modules.nix new file mode 100644 index 00000000000..071809daa58 --- /dev/null +++ b/lib/modules.nix @@ -0,0 +1,312 @@ +with import ./lists.nix; +with import ./trivial.nix; +with import ./attrsets.nix; +with import ./options.nix; +with import ./debug.nix; +with import ./types.nix; + +rec { + + /* Evaluate a set of modules. The result is a set of two + attributes: ‘options’: the nested set of all option declarations, + and ‘config’: the nested set of all option values. */ + evalModules = { modules, prefix ? [], args ? {}, check ? true }: + let + args' = args // result; + closed = closeModules modules args'; + # Note: the list of modules is reversed to maintain backward + # compatibility with the old module system. Not sure if this is + # the most sensible policy. + options = mergeModules prefix (reverseList closed); + # Traverse options and extract the option values into the final + # config set. At the same time, check whether all option + # definitions have matching declarations. + config = yieldConfig prefix options; + yieldConfig = prefix: set: + let res = removeAttrs (mapAttrs (n: v: + if isOption v then v.value + else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"]; + in + if check && set ? _definedNames then + fold (m: res: + fold (name: res: + if hasAttr name set then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.") + res m.names) + res set._definedNames + else + res; + result = { inherit options config; }; + in result; + + /* Close a set of modules under the ‘imports’ relation. */ + closeModules = modules: args: + let + toClosureList = file: parentKey: imap (n: x: + if isAttrs x || builtins.isFunction x then + unifyModuleSyntax file "${parentKey}:anon-${toString n}" (applyIfFunction x args) + else + unifyModuleSyntax (toString x) (toString x) (applyIfFunction (import x) args)); + in + builtins.genericClosure { + startSet = toClosureList unknownModule "" modules; + operator = m: toClosureList m.file m.key m.imports; + }; + + /* Massage a module into canonical form, that is, a set consisting + of ‘options’, ‘config’ and ‘imports’ attributes. */ + unifyModuleSyntax = file: key: m: + if m ? config || m ? options then + let badAttrs = removeAttrs m ["imports" "options" "config" "key" "_file"]; in + if badAttrs != {} then + throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'." + else + { file = m._file or file; + key = toString m.key or key; + imports = m.imports or []; + options = m.options or {}; + config = m.config or {}; + } + else + { file = m._file or file; + key = toString m.key or key; + imports = m.require or [] ++ m.imports or []; + options = {}; + config = removeAttrs m ["key" "_file" "require" "imports"]; + }; + + applyIfFunction = f: arg: if builtins.isFunction f then f arg else f; + + /* Merge a list of modules. This will recurse over the option + declarations in all modules, combining them into a single set. + At the same time, for each option declaration, it will merge the + corresponding option definitions in all machines, returning them + in the ‘value’ attribute of each option. */ + mergeModules = prefix: modules: + mergeModules' prefix modules + (concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules); + + mergeModules' = prefix: options: configs: + listToAttrs (map (name: { + # We're descending into attribute ‘name’. + inherit name; + value = + let + loc = prefix ++ [name]; + # Get all submodules that declare ‘name’. + decls = concatLists (map (m: + if hasAttr name m.options + then [ { inherit (m) file; options = getAttr name m.options; } ] + else [] + ) options); + # Get all submodules that define ‘name’. + defns = concatLists (map (m: + if hasAttr name m.config + then map (config: { inherit (m) file; inherit config; }) + (pushDownProperties (getAttr name m.config)) + else [] + ) configs); + nrOptions = count (m: isOption m.options) decls; + # Process mkMerge and mkIf properties. + defns' = concatMap (m: + if hasAttr name m.config + then map (m': { inherit (m) file; value = m'; }) (dischargeProperties (getAttr name m.config)) + else [] + ) configs; + in + if nrOptions == length decls then + let opt = fixupOptionType loc (mergeOptionDecls loc decls); + in evalOptionValue loc opt defns' + else if nrOptions != 0 then + let + firstOption = findFirst (m: isOption m.options) "" decls; + firstNonOption = findFirst (m: !isOption m.options) "" decls; + in + throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'." + else + mergeModules' loc decls defns; + }) (concatMap (m: attrNames m.options) options)) + // { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; }; + + /* Merge multiple option declarations into a single declaration. In + general, there should be only one declaration of each option. + The exception is the ‘options’ attribute, which specifies + sub-options. These can be specified multiple times to allow one + module to add sub-options to an option declared somewhere else + (e.g. multiple modules define sub-options for ‘fileSystems’). */ + mergeOptionDecls = loc: opts: + fold (opt: res: + if opt.options ? default && res ? default || + opt.options ? example && res ? example || + opt.options ? description && res ? description || + opt.options ? apply && res ? apply || + opt.options ? type && res ? type + then + throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}." + else + opt.options // res // + { declarations = [opt.file] ++ res.declarations; + options = if opt.options ? options then [(toList opt.options.options ++ res.options)] else []; + } + ) { inherit loc; declarations = []; options = []; } opts; + + /* Merge all the definitions of an option to produce the final + config value. */ + evalOptionValue = loc: opt: defs: + let + # Process mkOverride properties, adding in the default + # value specified in the option declaration (if any). + defsFinal = filterOverrides + ((if opt ? default then [{ file = head opt.declarations; value = mkOptionDefault opt.default; }] else []) ++ defs); + files = map (def: def.file) defsFinal; + # Type-check the remaining definitions, and merge them if + # possible. + merged = + if defsFinal == [] then + throw "The option `${showOption loc}' is used but not defined." + else + fold (def: res: + if opt.type.check def.value then res + else throw "The option value `${showOption loc}' in `${def.file}' is not a ${opt.type.name}.") + (opt.type.merge loc defsFinal) defsFinal; + # Finally, apply the ‘apply’ function to the merged + # value. This allows options to yield a value computed + # from the definitions. + value = (opt.apply or id) merged; + in opt // + { value = addErrorContext "while evaluating the option `${showOption loc}':" value; + definitions = map (def: def.value) defsFinal; + isDefined = defsFinal != []; + inherit files; + }; + + /* Given a config set, expand mkMerge properties, and push down the + mkIf properties into the children. The result is a list of + config sets that do not have properties at top-level. For + example, + + mkMerge [ { boot = set1; } (mkIf cond { boot = set2; services = set3; }) ] + + is transformed into + + [ { boot = set1; } { boot = mkIf cond set2; services mkIf cond set3; } ]. + + This transform is the critical step that allows mkIf conditions + to refer to the full configuration without creating an infinite + recursion. + */ + pushDownProperties = cfg: + if cfg._type or "" == "merge" then + concatMap pushDownProperties cfg.contents + else if cfg._type or "" == "if" then + map (mapAttrs (n: v: mkIf cfg.condition v)) (pushDownProperties cfg.content) + else if cfg._type or "" == "override" then + map (mapAttrs (n: v: mkOverride cfg.priority v)) (pushDownProperties cfg.content) + else + [ cfg ]; + + /* Given a config value, expand mkMerge properties, and discharge + any mkIf conditions. That is, this is the place where mkIf + conditions are actually evaluated. The result is a list of + config values. For example, ‘mkIf false x’ yields ‘[]’, + ‘mkIf true x’ yields ‘[x]’, and + + mkMerge [ 1 (mkIf true 2) (mkIf true (mkIf false 3)) ] + + yields ‘[ 1 2 ]’. + */ + dischargeProperties = def: + if def._type or "" == "merge" then + concatMap dischargeProperties def.contents + else if def._type or "" == "if" then + if def.condition then + dischargeProperties def.content + else + [ ] + else + [ def ]; + + /* Given a list of config values, process the mkOverride properties, + that is, return the values that have the highest (that is, + numerically lowest) priority, and strip the mkOverride + properties. For example, + + [ { file = "/1"; value = mkOverride 10 "a"; } + { file = "/2"; value = mkOverride 20 "b"; } + { file = "/3"; value = "z"; } + { file = "/4"; value = mkOverride 10 "d"; } + ] + + yields + + [ { file = "/1"; value = "a"; } + { file = "/4"; value = "d"; } + ] + + Note that "z" has the default priority 100. + */ + filterOverrides = defs: + let + defaultPrio = 100; + getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio; + min = x: y: if builtins.lessThan x y then x else y; + highestPrio = fold (def: prio: min (getPrio def) prio) 9999 defs; + strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def; + in concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; + + /* Hack for backward compatibility: convert options of type + optionSet to configOf. FIXME: remove eventually. */ + fixupOptionType = loc: opt: + let + options' = opt.options or + (throw "Option `${showOption loc'}' has type optionSet but has no option attribute."); + coerce = x: + if builtins.isFunction x then x + else { config, ... }: { options = x; }; + options = map coerce (flatten options'); + f = tp: + if tp.name == "option set" then types.submodule options + else if tp.name == "attribute set of option sets" then types.attrsOf (types.submodule options) + else if tp.name == "list or attribute set of option sets" then types.loaOf (types.submodule options) + else if tp.name == "list of option sets" then types.listOf (types.submodule options) + else if tp.name == "null or option set" then types.nullOr (types.submodule options) + else tp; + in opt // { type = f (opt.type or types.unspecified); }; + + + /* Properties. */ + + mkIf = condition: content: + { _type = "if"; + inherit condition content; + }; + + mkAssert = assertion: message: content: + mkIf + (if assertion then true else throw "\nFailed assertion: ${message}") + content; + + mkMerge = contents: + { _type = "merge"; + inherit contents; + }; + + mkOverride = priority: content: + { _type = "override"; + inherit priority content; + }; + + mkOptionDefault = mkOverride 1001; # priority of option defaults + mkDefault = mkOverride 1000; # used in config sections of non-user modules to set a default + mkForce = mkOverride 50; + mkVMOverride = mkOverride 10; # used by ‘nixos-rebuild build-vm’ + + mkFixStrictness = id; # obsolete, no-op + + # FIXME: Add mkOrder back in. It's not currently used anywhere in + # NixOS, but it should be useful. + + + /* Compatibility. */ + fixMergeModules = modules: args: evalModules { inherit modules args; check = false; }; + +} diff --git a/lib/options.nix b/lib/options.nix new file mode 100644 index 00000000000..63798c4faa3 --- /dev/null +++ b/lib/options.nix @@ -0,0 +1,120 @@ +# Nixpkgs/NixOS option handling. + +let lib = import ./default.nix; in + +with import ./trivial.nix; +with import ./lists.nix; +with import ./misc.nix; +with import ./attrsets.nix; +with import ./strings.nix; + +rec { + + isOption = lib.isType "option"; + mkOption = + { default ? null # Default value used when no definition is given in the configuration. + , defaultText ? null # Textual representation of the default, for in the manual. + , example ? null # Example value used in the manual. + , description ? null # String describing the option. + , type ? null # Option type, providing type-checking and value merging. + , apply ? null # Function that converts the option value to something else. + , internal ? null # Whether the option is for NixOS developers only. + , visible ? null # Whether the option shows up in the manual. + , options ? null # Obsolete, used by types.optionSet. + } @ attrs: + attrs // { _type = "option"; }; + + mkEnableOption = name: mkOption { + default = false; + example = true; + description = "Whether to enable ${name}."; + type = lib.types.bool; + }; + + mergeDefaultOption = loc: defs: + let list = getValues defs; in + if length list == 1 then head list + else if all builtins.isFunction list then x: mergeDefaultOption loc (map (f: f x) list) + else if all isList list then concatLists list + else if all isAttrs list then fold lib.mergeAttrs {} list + else if all builtins.isBool list then fold lib.or false list + else if all builtins.isString list then lib.concatStrings list + else if all builtins.isInt list && all (x: x == head list) list then head list + else throw "Cannot merge definitions of `${showOption loc}' given in ${showFiles (getFiles defs)}."; + + /* Obsolete, will remove soon. Specify an option type or apply + function instead. */ + mergeTypedOption = typeName: predicate: merge: loc: list: + let list' = map (x: x.value) list; in + if all predicate list then merge list' + else throw "Expected a ${typeName}."; + + mergeEnableOption = mergeTypedOption "boolean" + (x: true == x || false == x) (fold lib.or false); + + mergeListOption = mergeTypedOption "list" isList concatLists; + + mergeStringOption = mergeTypedOption "string" builtins.isString lib.concatStrings; + + mergeOneOption = loc: defs: + if defs == [] then abort "This case should never happen." + else if length defs != 1 then + throw "The unique option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}." + else (head defs).value; + + getValues = map (x: x.value); + getFiles = map (x: x.file); + + + # Generate documentation template from the list of option declaration like + # the set generated with filterOptionSets. + optionAttrSetToDocList = optionAttrSetToDocList' []; + + optionAttrSetToDocList' = prefix: options: + fold (opt: rest: + let + docOption = rec { + name = showOption opt.loc; + description = opt.description or (throw "Option `${name}' has no description."); + declarations = filter (x: x != unknownModule) opt.declarations; + internal = opt.internal or false; + visible = opt.visible or true; + } + // optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; } + // optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; } + // optionalAttrs (opt ? defaultText) { default = opt.defaultText; }; + + subOptions = + let ss = opt.type.getSubOptions opt.loc; + in if ss != {} then optionAttrSetToDocList' opt.loc ss else []; + in + # FIXME: expensive, O(n^2) + [ docOption ] ++ subOptions ++ rest) [] (collect isOption options); + + + /* This function recursively removes all derivation attributes from + `x' except for the `name' attribute. This is to make the + generation of `options.xml' much more efficient: the XML + representation of derivations is very large (on the order of + megabytes) and is not actually used by the manual generator. */ + scrubOptionValue = x: + if isDerivation x then + { type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; } + else if isList x then map scrubOptionValue x + else if isAttrs x then mapAttrs (n: v: scrubOptionValue v) (removeAttrs x ["_args"]) + else x; + + + /* For use in the ‘example’ option attribute. It causes the given + text to be included verbatim in documentation. This is necessary + for example values that are not simple values, e.g., + functions. */ + literalExample = text: { _type = "literalExample"; inherit text; }; + + + /* Helper functions. */ + showOption = concatStringsSep "."; + showFiles = files: concatStringsSep " and " (map (f: "`${f}'") files); + unknownModule = ""; + +} diff --git a/pkgs/lib/platforms.nix b/lib/platforms.nix similarity index 100% rename from pkgs/lib/platforms.nix rename to lib/platforms.nix diff --git a/pkgs/lib/sources.nix b/lib/sources.nix similarity index 100% rename from pkgs/lib/sources.nix rename to lib/sources.nix diff --git a/pkgs/lib/strings-with-deps.nix b/lib/strings-with-deps.nix similarity index 100% rename from pkgs/lib/strings-with-deps.nix rename to lib/strings-with-deps.nix diff --git a/pkgs/lib/strings.nix b/lib/strings.nix similarity index 100% rename from pkgs/lib/strings.nix rename to lib/strings.nix diff --git a/pkgs/lib/systems.nix b/lib/systems.nix similarity index 97% rename from pkgs/lib/systems.nix rename to lib/systems.nix index 1ef869fb012..afa2002c6e4 100644 --- a/pkgs/lib/systems.nix +++ b/lib/systems.nix @@ -22,7 +22,7 @@ rec { }; - isCpuType = x: typeOf x == "cpu-type" + isCpuType = x: isType "cpu-type" x && elem x.bits [8 16 32 64 128] && (builtins.lessThan 8 x.bits -> isSignificantByte x.significantByte); @@ -69,7 +69,7 @@ rec { }; - isSystem = x: typeOf x == "system" + isSystem = x: isType "system" x && isCpuType x.cpu && isArchitecture x.arch && isKernel x.kernel; diff --git a/pkgs/lib/tests.nix b/lib/tests.nix similarity index 100% rename from pkgs/lib/tests.nix rename to lib/tests.nix diff --git a/pkgs/lib/trivial.nix b/lib/trivial.nix similarity index 100% rename from pkgs/lib/trivial.nix rename to lib/trivial.nix diff --git a/lib/types.nix b/lib/types.nix new file mode 100644 index 00000000000..09b29a762e1 --- /dev/null +++ b/lib/types.nix @@ -0,0 +1,210 @@ +# Definitions related to run-time type checking. Used in particular +# to type-check NixOS configurations. + +with import ./lists.nix; +with import ./attrsets.nix; +with import ./options.nix; +with import ./trivial.nix; +with import ./strings.nix; + +rec { + + isType = type: x: (x._type or "") == type; + typeOf = x: x._type or ""; + + setType = typeName: value: value // { + _type = typeName; + }; + + + isOptionType = isType "option-type"; + mkOptionType = + { # Human-readable representation of the type. + name + , # Function applied to each definition that should return true if + # its type-correct, false otherwise. + check ? (x: true) + , # Merge a list of definitions together into a single value. + # This function is called with two arguments: the location of + # the option in the configuration as a list of strings + # (e.g. ["boot" "loader "grub" "enable"]), and a list of + # definition values and locations (e.g. [ { file = "/foo.nix"; + # value = 1; } { file = "/bar.nix"; value = 2 } ]). + merge ? mergeDefaultOption + , # Return a flat list of sub-options. Used to generate + # documentation. + getSubOptions ? prefix: {} + }: + { _type = "option-type"; + inherit name check merge getSubOptions; + }; + + + types = rec { + + unspecified = mkOptionType { + name = "unspecified"; + }; + + bool = mkOptionType { + name = "boolean"; + check = builtins.isBool; + merge = loc: fold (x: y: x.value || y) false; + }; + + int = mkOptionType { + name = "integer"; + check = builtins.isInt; + merge = mergeOneOption; + }; + + str = mkOptionType { + name = "string"; + check = builtins.isString; + merge = mergeOneOption; + }; + + # Merge multiple definitions by concatenating them (with the given + # separator between the values). + separatedString = sep: mkOptionType { + name = "string"; + check = builtins.isString; + merge = loc: defs: concatStringsSep sep (getValues defs); + }; + + lines = separatedString "\n"; + commas = separatedString ","; + envVar = separatedString ":"; + + # Deprecated; should not be used because it quietly concatenates + # strings, which is usually not what you want. + string = separatedString ""; + + attrs = mkOptionType { + name = "attribute set"; + check = isAttrs; + merge = loc: fold (def: mergeAttrs def.value) {}; + }; + + # derivation is a reserved keyword. + package = mkOptionType { + name = "derivation"; + check = isDerivation; + merge = mergeOneOption; + }; + + path = mkOptionType { + name = "path"; + # Hacky: there is no ‘isPath’ primop. + check = x: builtins.unsafeDiscardStringContext (builtins.substring 0 1 (toString x)) == "/"; + merge = mergeOneOption; + }; + + # drop this in the future: + list = builtins.trace "`types.list' is deprecated; use `types.listOf' instead" types.listOf; + + listOf = elemType: mkOptionType { + name = "list of ${elemType.name}s"; + check = value: isList value && all elemType.check value; + merge = loc: defs: + concatLists (imap (n: def: imap (m: def': + elemType.merge (loc ++ ["[${toString n}-${toString m}]"]) + [{ inherit (def) file; value = def'; }]) def.value) defs); + getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]); + }; + + attrsOf = elemType: mkOptionType { + name = "attribute set of ${elemType.name}s"; + check = x: isAttrs x && all elemType.check (attrValues x); + merge = loc: defs: + zipAttrsWith (name: elemType.merge (loc ++ [name])) + # Push down position info. + (map (def: listToAttrs (mapAttrsToList (n: def': + { name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs); + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [""]); + }; + + # List or attribute set of ... + loaOf = elemType: + let + convertIfList = defIdx: def: + if isList def.value then + { inherit (def) file; + value = listToAttrs ( + imap (elemIdx: elem: + { name = "unnamed-${toString defIdx}.${toString elemIdx}"; + value = elem; + }) def.value); + } + else + def; + listOnly = listOf elemType; + attrOnly = attrsOf elemType; + in mkOptionType { + name = "list or attribute set of ${elemType.name}s"; + check = x: + if isList x then listOnly.check x + else if isAttrs x then attrOnly.check x + else false; + merge = loc: defs: attrOnly.merge loc (imap convertIfList defs); + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [""]); + }; + + uniq = elemType: mkOptionType { + inherit (elemType) name check; + merge = mergeOneOption; + getSubOptions = elemType.getSubOptions; + }; + + nullOr = elemType: mkOptionType { + name = "null or ${elemType.name}"; + check = x: builtins.isNull x || elemType.check x; + merge = loc: defs: + let nrNulls = count (def: isNull def.value) defs; in + if nrNulls == length defs then null + else if nrNulls != 0 then + throw "The option `${showOption loc}' is defined both null and not null, in ${showFiles (getFiles defs)}." + else elemType.merge loc defs; + getSubOptions = elemType.getSubOptions; + }; + + functionTo = elemType: mkOptionType { + name = "function that evaluates to a(n) ${elemType.name}"; + check = builtins.isFunction; + merge = loc: defs: + fnArgs: elemType.merge loc (map (fn: { inherit (fn) file; value = fn.value fnArgs; }) defs); + getSubOptions = elemType.getSubOptions; + }; + + submodule = opts: + let + opts' = toList opts; + inherit (import ./modules.nix) evalModules; + in + mkOptionType rec { + name = "submodule"; + check = x: isAttrs x || builtins.isFunction x; + merge = loc: defs: + let + coerce = def: if builtins.isFunction def then def else { config = def; }; + modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs; + in (evalModules { inherit modules; args.name = last loc; prefix = loc; }).config; + getSubOptions = prefix: (evalModules + { modules = opts'; inherit prefix; + # FIXME: hack to get shit to evaluate. + args = { name = ""; }; }).options; + }; + + # Obsolete alternative to configOf. It takes its option + # declarations from the ‘options’ attribute of containing option + # declaration. + optionSet = mkOptionType { + name = /* builtins.trace "types.optionSet is deprecated; use types.submodule instead" */ "option set"; + }; + + # Augment the given type with an additional type check function. + addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; }; + + }; + +} diff --git a/maintainers/docs/uclibc-cross.txt b/maintainers/docs/uclibc-cross.txt deleted file mode 100644 index c32a95eb2b2..00000000000 --- a/maintainers/docs/uclibc-cross.txt +++ /dev/null @@ -1,27 +0,0 @@ -Adding uClibc support for a new platform - -Sometimes you want to cross-compile to another architecture, for example an -embedded devices. For embedded devices the uClibc C library is popular. -In Nixpkgs there is support for uClibc for several architectures but not -everything is supported. - -Adding support is not very difficult, - -* Add your architecture to the buildfiles in -$nixpkgs/development/tools/misc/binutils-cross - -* Add your architecture to the buildfiles in -$nixpkgs/development/compilers/gcc-4.0-cross - -* Add your architecture to the buildfiles in -$nixpkgs/os-specific/linux/kernel-headers-cross - -* Add your architecture to the buildfiles in -$nixpkgs/development/uclibc - -In the latter directory you will also need a configuration file for uClibc. -You can make these by unpacking the uClibc sources and run a "make menuconfig". -In the configuration a few things need to be adapted: - -- kernel sources -> need to point at our own kernel headers -- install -> needs to point at $out diff --git a/maintainers/scripts/eval-release.nix b/maintainers/scripts/eval-release.nix index 4bd2b0f1fa8..bb9572cbc79 100644 --- a/maintainers/scripts/eval-release.nix +++ b/maintainers/scripts/eval-release.nix @@ -1,7 +1,7 @@ # Evaluate `release.nix' like Hydra would. Too bad nix-instantiate # can't to do this. -with import ../../pkgs/lib; +with import ../../lib; let trace = if builtins.getEnv "VERBOSE" == "1" then builtins.trace else (x: y: y); @@ -10,14 +10,15 @@ let # Add the ‘recurseForDerivations’ attribute to ensure that # nix-instantiate recurses into nested attribute sets. - recurse = attrs: + recurse = path: attrs: if (builtins.tryEval attrs).success then - if isDerivation attrs + if isDerivation attrs then - if (builtins.tryEval attrs.outPath).success - then attrs - else { } - else { recurseForDerivations = true; } // mapAttrs (n: v: recurse v) attrs + if (builtins.tryEval attrs.drvPath).success + then { inherit (attrs) name drvPath; } + else { failed = true; } + else { recurseForDerivations = true; } // + mapAttrs (n: v: let path' = path ++ [n]; in trace path' (recurse path' v)) attrs else { }; -in recurse rel +in recurse [] rel diff --git a/nixos/.topmsg b/nixos/.topmsg new file mode 100644 index 00000000000..9632e592631 --- /dev/null +++ b/nixos/.topmsg @@ -0,0 +1 @@ +improvements to vsftpd module diff --git a/nixos/COPYING b/nixos/COPYING new file mode 100644 index 00000000000..c9b44cb8aae --- /dev/null +++ b/nixos/COPYING @@ -0,0 +1,18 @@ +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/nixos/README b/nixos/README new file mode 100644 index 00000000000..4ecf648a930 --- /dev/null +++ b/nixos/README @@ -0,0 +1,5 @@ +*** NixOS *** + +NixOS is a Linux distribution based on the purely functional package +management system Nix. More information can be found at +http://nixos.org/nixos and in the manual in doc/manual. diff --git a/nixos/default.nix b/nixos/default.nix new file mode 100644 index 00000000000..5d69b79e13a --- /dev/null +++ b/nixos/default.nix @@ -0,0 +1,43 @@ +{ configuration ? import ./lib/from-env.nix "NIXOS_CONFIG" +, system ? builtins.currentSystem +}: + +let + + eval = import ./lib/eval-config.nix { + inherit system; + modules = [ configuration ]; + }; + + inherit (eval) pkgs; + + # This is for `nixos-rebuild build-vm'. + vmConfig = (import ./lib/eval-config.nix { + inherit system; + modules = [ configuration ./modules/virtualisation/qemu-vm.nix ]; + }).config; + + # This is for `nixos-rebuild build-vm-with-bootloader'. + vmWithBootLoaderConfig = (import ./lib/eval-config.nix { + inherit system; + modules = + [ configuration + ./modules/virtualisation/qemu-vm.nix + { virtualisation.useBootLoader = true; } + ]; + }).config; + +in + +{ + inherit (eval) config options; + + system = eval.config.system.build.toplevel; + + vm = vmConfig.system.build.vm; + + vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm; + + # The following are used by nixos-rebuild. + nixFallback = pkgs.nixUnstable; +} diff --git a/nixos/doc/config-examples/basic.nix b/nixos/doc/config-examples/basic.nix new file mode 100644 index 00000000000..da37cfb8c28 --- /dev/null +++ b/nixos/doc/config-examples/basic.nix @@ -0,0 +1,21 @@ +{ + boot = { + loader.grub.device = "/dev/sda"; + }; + + fileSystems = [ + { mountPoint = "/"; + device = "/dev/sda1"; + } + ]; + + swapDevices = [ + { device = "/dev/sdb1"; } + ]; + + services = { + openssh = { + enable = true; + }; + }; +} diff --git a/nixos/doc/config-examples/closed-install-configuration.nix b/nixos/doc/config-examples/closed-install-configuration.nix new file mode 100644 index 00000000000..0cebacdb0cc --- /dev/null +++ b/nixos/doc/config-examples/closed-install-configuration.nix @@ -0,0 +1,32 @@ +{ + boot = { + loader.grub.device = "/dev/sda"; + copyKernels = true; + bootMount = "(hd0,0)"; + }; + + fileSystems = [ + { mountPoint = "/"; + device = "/dev/sda3"; + } + { mountPoint = "/boot"; + device = "/dev/sda1"; + neededForBoot = true; + } + ]; + + swapDevices = [ + { device = "/dev/sda2"; } + ]; + + services = { + sshd = { + enable = true; + }; + }; + + fonts = { + enableFontConfig = false; + }; + +} diff --git a/nixos/doc/config-examples/root-on-lvm.nix b/nixos/doc/config-examples/root-on-lvm.nix new file mode 100644 index 00000000000..2ea1e547921 --- /dev/null +++ b/nixos/doc/config-examples/root-on-lvm.nix @@ -0,0 +1,27 @@ +# This configuration has / on a LVM volume. Since Grub +# doesn't know about LVM, a separate /boot is therefore +# needed. +# +# In this example, labels are used for file systems and +# swap devices: "boot" might be /dev/sda1, "root" might be +# /dev/my-volume-group/root, and "swap" might be /dev/sda2. +# In particular there is no specific reference to the fact +# that / is on LVM; that's figured out automatically. + +{ + boot.loader.grub.device = "/dev/sda"; + boot.initrd.kernelModules = ["ata_piix"]; + + fileSystems = [ + { mountPoint = "/"; + label = "root"; + } + { mountPoint = "/boot"; + label = "boot"; + } + ]; + + swapDevices = [ + { label = "swap"; } + ]; +} diff --git a/nixos/doc/config-examples/svn-server.nix b/nixos/doc/config-examples/svn-server.nix new file mode 100644 index 00000000000..e727007117b --- /dev/null +++ b/nixos/doc/config-examples/svn-server.nix @@ -0,0 +1,36 @@ +{ + boot = { + loader.grub.device = "/dev/sda"; + }; + + fileSystems = [ + { mountPoint = "/"; + device = "/dev/sda1"; + } + ]; + + services = { + + sshd = { + enable = true; + }; + + httpd = { + enable = true; + adminAddr = "admin@example.org"; + + subservices = { + + subversion = { + enable = true; + dataDir = "/data/subversion"; + notificationSender = "svn@example.org"; + }; + + }; + + }; + + }; + +} diff --git a/nixos/doc/config-examples/x86_64-usbstick.nix b/nixos/doc/config-examples/x86_64-usbstick.nix new file mode 100644 index 00000000000..374d3ba3bc7 --- /dev/null +++ b/nixos/doc/config-examples/x86_64-usbstick.nix @@ -0,0 +1,20 @@ +# Configuration file used to install NixOS-x86_64 on a USB stick. + +{ + boot = { + loader.grub.device = "/dev/sda"; + initrd = { + kernelModules = ["usb_storage" "ehci_hcd" "ohci_hcd"]; + }; + }; + + fileSystems = [ + { mountPoint = "/"; + label = "nixos-usb"; + } + ]; + + fonts = { + enableFontConfig = false; + }; +} diff --git a/nixos/doc/manual/configuration.xml b/nixos/doc/manual/configuration.xml new file mode 100644 index 00000000000..9bca53ae904 --- /dev/null +++ b/nixos/doc/manual/configuration.xml @@ -0,0 +1,1515 @@ + + +Configuring NixOS + +This chapter describes how to configure various aspects of a +NixOS machine through the configuration file +/etc/nixos/configuration.nix. As described in +, changes to this file only take +effect after you run nixos-rebuild. + + + + +
Configuration syntax + +
The basics + +The NixOS configuration file +/etc/nixos/configuration.nix is actually a +Nix expression, which is the Nix package +manager’s purely functional language for describing how to build +packages and configurations. This means you have all the expressive +power of that language at your disposal, including the ability to +abstract over common patterns, which is very useful when managing +complex systems. The syntax and semantics of the Nix language are +fully described in the Nix +manual, but here we give a short overview of the most important +constructs useful in NixOS configuration files. + +The NixOS configuration file generally looks like this: + + +{ config, pkgs, ... }: + +{ option definitions +} + + +The first line ({ config, pkgs, ... }:) denotes +that this is actually a function that takes at least the two arguments + config and pkgs. (These are +explained later.) The function returns a set of +option definitions ({ ... }). These definitions have the +form name = +value, where +name is the name of an option and +value is its value. For example, + + +{ config, pkgs, ... }: + +{ services.httpd.enable = true; + services.httpd.adminAddr = "alice@example.org"; + services.httpd.documentRoot = "/webroot"; +} + + +defines a configuration with three option definitions that together +enable the Apache HTTP Server with /webroot as +the document root. + +Sets can be nested, and in fact dots in option names are +shorthand for defining a set containing another set. For instance, + defines a set named +services that contains a set named +httpd, which in turn contains an option definition +named enable with value true. +This means that the example above can also be written as: + + +{ config, pkgs, ... }: + +{ services = { + httpd = { + enable = true; + adminAddr = "alice@example.org"; + documentRoot = "/webroot"; + }; + }; +} + + +which may be more convenient if you have lots of option definitions +that share the same prefix (such as +services.httpd). + +NixOS checks your option definitions for correctness. For +instance, if you try to define an option that doesn’t exist (that is, +doesn’t have a corresponding option declaration), +nixos-rebuild will give an error like: + +The option `services.httpd.enabl' defined in `/etc/nixos/configuration.nix' does not exist. + +Likewise, values in option definitions must have a correct type. For +instance, must be a Boolean +(true or false). Trying to give +it a value of another type, such as a string, will cause an error: + +The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean. + + + + +Options have various types of values. The most important are: + + + + Strings + + Strings are enclosed in double quotes, e.g. + + +networking.hostName = "dexter"; + + + Special characters can be escaped by prefixing them with a + backslash (e.g. \"). + + Multi-line strings can be enclosed in double + single quotes, e.g. + + +networking.extraHosts = + '' + 127.0.0.2 other-localhost + 10.0.0.1 server + ''; + + + The main difference is that preceding whitespace is + automatically stripped from each line, and that characters like + " and \ are not special + (making it more convenient for including things like shell + code). + + + + + Booleans + + These can be true or + false, e.g. + + +networking.firewall.enable = true; +networking.firewall.allowPing = false; + + + + + + + Integers + + For example, + + +boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60; + + + (Note that here the attribute name + net.ipv4.tcp_keepalive_time is enclosed in + quotes to prevent it from being interpreted as a set named + net containing a set named + ipv4, and so on. This is because it’s not a + NixOS option but the literal name of a Linux kernel + setting.) + + + + + Sets + + Sets were introduced above. They are name/value pairs + enclosed in braces, as in the option definition + + +fileSystems."/boot" = + { device = "/dev/sda1"; + fsType = "ext4"; + options = "rw,data=ordered,relatime"; + }; + + + + + + + Lists + + The important thing to note about lists is that list + elements are separated by whitespace, like this: + + +boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ]; + + + List elements can be any other type, e.g. sets: + + +swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; + + + + + + + Packages + + Usually, the packages you need are already part of the Nix + Packages collection, which is a set that can be accessed through + the function argument pkgs. Typical uses: + + +environment.systemPackages = + [ pkgs.thunderbird + pkgs.emacs + ]; + +postgresql.package = pkgs.postgresql90; + + + The latter option definition changes the default PostgreSQL + package used by NixOS’s PostgreSQL service to 9.0. For more + information on packages, including how to add new ones, see + . + + + + + + + +
+ + +
Abstractions + +If you find yourself repeating yourself over and over, it’s time +to abstract. Take, for instance, this Apache HTTP Server configuration: + + +{ + services.httpd.virtualHosts = + [ { hostName = "example.org"; + documentRoot = "/webroot"; + adminAddr = "alice@example.org"; + enableUserDir = true; + } + { hostName = "example.org"; + documentRoot = "/webroot"; + adminAddr = "alice@example.org"; + enableUserDir = true; + enableSSL = true; + sslServerCert = "/root/ssl-example-org.crt"; + sslServerKey = "/root/ssl-example-org.key"; + } + ]; +} + + +It defines two virtual hosts with nearly identical configuration; the +only difference is that the second one has SSL enabled. To prevent +this duplication, we can use a let: + + +let + exampleOrgCommon = + { hostName = "example.org"; + documentRoot = "/webroot"; + adminAddr = "alice@example.org"; + enableUserDir = true; + }; +in +{ + services.httpd.virtualHosts = + [ exampleOrgCommon + (exampleOrgCommon // { + enableSSL = true; + sslServerCert = "/root/ssl-example-org.crt"; + sslServerKey = "/root/ssl-example-org.key"; + }) + ]; +} + + +The let exampleOrgCommon = +... defines a variable named +exampleOrgCommon. The // +operator merges two attribute sets, so the configuration of the second +virtual host is the set exampleOrgCommon extended +with the SSL options. + +You can write a let wherever an expression is +allowed. Thus, you also could have written: + + +{ + services.httpd.virtualHosts = + let exampleOrgCommon = ...; in + [ exampleOrgCommon + (exampleOrgCommon // { ... }) + ]; +} + + +but not { let exampleOrgCommon = +...; in ...; +} since attributes (as opposed to attribute values) are not +expressions. + +Functions provide another method of +abstraction. For instance, suppose that we want to generate lots of +different virtual hosts, all with identical configuration except for +the host name. This can be done as follows: + + +{ + services.httpd.virtualHosts = + let + makeVirtualHost = name: + { hostName = name; + documentRoot = "/webroot"; + adminAddr = "alice@example.org"; + }; + in + [ (makeVirtualHost "example.org") + (makeVirtualHost "example.com") + (makeVirtualHost "example.gov") + (makeVirtualHost "example.nl") + ]; +} + + +Here, makeVirtualHost is a function that takes a +single argument name and returns the configuration +for a virtual host. That function is then called for several names to +produce the list of virtual host configurations. + +We can further improve on this by using the function +map, which applies another function to every +element in a list: + + +{ + services.httpd.virtualHosts = + let + makeVirtualHost = ...; + in map makeVirtualHost + [ "example.org" "example.com" "example.gov" "example.nl" ]; +} + + +(The function map is called a +higher-order function because it takes another +function as an argument.) + +What if you need more than one argument, for instance, if we +want to use a different documentRoot for each +virtual host? Then we can make makeVirtualHost a +function that takes a set as its argument, like this: + + +{ + services.httpd.virtualHosts = + let + makeVirtualHost = { name, root }: + { hostName = name; + documentRoot = root; + adminAddr = "alice@example.org"; + }; + in map makeVirtualHost + [ { name = "example.org"; root = "/sites/example.org"; } + { name = "example.com"; root = "/sites/example.com"; } + { name = "example.gov"; root = "/sites/example.gov"; } + { name = "example.nl"; root = "/sites/example.nl"; } + ]; +} + + +But in this case (where every root is a subdirectory of +/sites named after the virtual host), it would +have been shorter to define makeVirtualHost as + +makeVirtualHost = name: + { hostName = name; + documentRoot = "/sites/${name}"; + adminAddr = "alice@example.org"; + }; + + +Here, the construct +${...} allows the result +of an expression to be spliced into a string. + +
+ + +
Modularity + +The NixOS configuration mechanism is modular. If your +configuration.nix becomes too big, you can split +it into multiple files. Likewise, if you have multiple NixOS +configurations (e.g. for different computers) with some commonality, +you can move the common configuration into a shared file. + +Modules have exactly the same syntax as +configuration.nix. In fact, +configuration.nix is itself a module. You can +use other modules by including them from +configuration.nix, e.g.: + + +{ config, pkgs, ... }: + +{ imports = [ ./vpn.nix ./kde.nix ]; + services.httpd.enable = true; + environment.systemPackages = [ pkgs.emacs ]; + ... +} + + +Here, we include two modules from the same directory, +vpn.nix and kde.nix. The +latter might look like this: + + +{ config, pkgs, ... }: + +{ services.xserver.enable = true; + services.xserver.displayManager.kdm.enable = true; + services.xserver.desktopManager.kde4.enable = true; + environment.systemPackages = [ pkgs.kde4.kscreensaver ]; +} + + +Note that both configuration.nix and +kde.nix define the option +. When multiple modules +define an option, NixOS will try to merge the +definitions. In the case of +, that’s easy: the lists of +packages can simply be concatenated. For other types of options, a +merge may not be possible: for instance, if two modules define +, +nixos-rebuild will give an error: + + +The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'. + + +When that happens, it’s possible to force one definition take +precedence over the others: + + +services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org"; + + + + +When using multiple modules, you may need to access +configuration values defined in other modules. This is what the +config function argument is for: it contains the +complete, merged system configuration. That is, +config is the result of combining the +configurations returned by every moduleIf you’re +wondering how it’s possible that the (indirect) +result of a function is passed as an +input to that same function: that’s because Nix +is a “lazy” language — it only computes values when they are needed. +This works as long as no individual configuration value depends on +itself.. For example, here is a module that adds +some packages to only if + is set to +true somewhere else: + + +{ config, pkgs, ... }: + +{ environment.systemPackages = + if config.services.xserver.enable then + [ pkgs.firefox + pkgs.thunderbird + ] + else + [ ]; +} + + + + +With multiple modules, it may not be obvious what the final +value of a configuration option is. The command + allows you to find out: + + +$ nixos-option services.xserver.enable +true + +$ nixos-option boot.kernelModules +[ "tun" "ipv6" "loop" ... ] + + +Interactive exploration of the configuration is possible using +nix-repl, +a read-eval-print loop for Nix expressions. It’s not installed by +default; run nix-env -i nix-repl to get it. A +typical use: + + +$ nix-repl '<nixos>' + +nix-repl> config.networking.hostName +"mandark" + +nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts +[ "example.org" "example.gov" ] + + + + +
+ + +
Syntax summary + +Below is a summary of the most important syntactic constructs in +the Nix expression language. It’s not complete. In particular, there +are many other built-in functions. See the Nix +manual for the rest. + + + + + + + + Example + Description + + + + + + Basic values + + + "Hello world" + A string + + + "${pkgs.bash}/bin/sh" + A string containing an expression (expands to "/nix/store/hash-bash-version/bin/sh") + + + true, false + Booleans + + + 123 + An integer + + + ./foo.png + A path (relative to the containing Nix expression) + + + + Compound values + + + { x = 1; y = 2; } + An set with attributes names x and y + + + { foo.bar = 1; } + A nested set, equivalent to { foo = { bar = 1; }; } + + + rec { x = "bla"; y = x + "bar"; } + A recursive set, equivalent to { x = "foo"; y = "foobar"; } + + + [ "foo" "bar" ] + A list with two elements + + + + Operators + + + "foo" + "bar" + String concatenation + + + 1 + 2 + Integer addition + + + "foo" == "f" + "oo" + Equality test (evaluates to true) + + + "foo" != "bar" + Inequality test (evaluates to true) + + + !true + Boolean negation + + + { x = 1; y = 2; }.x + Attribute selection (evaluates to 1) + + + { x = 1; y = 2; }.z or 3 + Attribute selection with default (evaluates to 3) + + + { x = 1; y = 2; } // { z = 3; } + Merge two sets (attributes in the right-hand set taking precedence) + + + + Control structures + + + if 1 + 1 == 2 then "yes!" else "no!" + Conditional expression + + + assert 1 + 1 == 2; "yes!" + Assertion check (evaluates to "yes!") + + + let x = "foo"; y = "bar"; in x + y + Variable definition + + + with pkgs.lib; head [ 1 2 3 ] + Add all attributes from the given set to the scope + (evaluates to 1) + + + + Functions (lambdas) + + + x: x + 1 + A function that expects an integer and returns it increased by 1 + + + (x: x + 1) 100 + A function call (evaluates to 101) + + + let inc = x: x + 1; in inc (inc (inc 100)) + A function bound to a variable and subsequently called by name (evaluates to 103) + + + { x, y }: x + y + A function that expects a set with required attributes + x and y and concatenates + them + + + { x, y ? "bar" }: x + y + A function that expects a set with required attribute + x and optional y, using + "bar" as default value for + y + + + { x, y, ... }: x + y + A function that expects a set with required attributes + x and y and ignores any + other attributes + + + { x, y } @ args: x + y + A function that expects a set with required attributes + x and y, and binds the + whole set to args + + + + Built-in functions + + + import ./foo.nix + Load and return Nix expression in given file + + + map (x: x + x) [ 1 2 3 ] + Apply a function to every element of a list (evaluates to [ 2 4 6 ]) + + + + + + + +
+ + +
+ + + + +
Package management + +This section describes how to add additional packages to your +system. NixOS has two distinct styles of package management: + + + + Declarative, where you declare + what packages you want in your + configuration.nix. Every time you run + nixos-rebuild, NixOS will ensure that you get a + consistent set of binaries corresponding to your + specification. + + Ad hoc, where you install, + upgrade and uninstall packages via the nix-env + command. This style allows mixing packages from different Nixpkgs + versions. It’s the only choice for non-root + users. + + + + + +The next two sections describe these two styles. + + +
Declarative package management + +With declarative package management, you specify which packages +you want on your system by setting the option +. For instance, adding the +following line to configuration.nix enables the +Mozilla Thunderbird email application: + + +environment.systemPackages = [ pkgs.thunderbird ]; + + +The effect of this specification is that the Thunderbird package from +Nixpkgs will be built or downloaded as part of the system when you run +nixos-rebuild switch. + +You can get a list of the available packages as follows: + +$ nix-env -qaP '*' --description +nixos.pkgs.firefox firefox-23.0 Mozilla Firefox - the browser, reloaded +... + + +The first column in the output is the attribute +name, such as +nixos.pkgs.thunderbird. (The +nixos prefix allows distinguishing between +different channels that you might have.) + +To “uninstall” a package, simply remove it from + and run +nixos-rebuild switch. + + +
Customising packages + +Some packages in Nixpkgs have options to enable or disable +optional functionality or change other aspects of the package. For +instance, the Firefox wrapper package (which provides Firefox with a +set of plugins such as the Adobe Flash player) has an option to enable +the Google Talk plugin. It can be set in +configuration.nix as follows: + + +nixpkgs.config.firefox.enableGoogleTalkPlugin = true; + + + +Unfortunately, Nixpkgs currently lacks a way to query +available configuration options. + +Apart from high-level options, it’s possible to tweak a package +in almost arbitrary ways, such as changing or disabling dependencies +of a package. For instance, the Emacs package in Nixpkgs by default +has a dependency on GTK+ 2. If you want to build it against GTK+ 3, +you can specify that as follows: + + +environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ]; + + +The function override performs the call to the Nix +function that produces Emacs, with the original arguments amended by +the set of arguments specified by you. So here the function argument +gtk gets the value pkgs.gtk3, +causing Emacs to depend on GTK+ 3. (The parentheses are necessary +because in Nix, function application binds more weakly than list +construction, so without them, +environment.systemPackages would be a list with two +elements.) + +Even greater customisation is possible using the function +overrideDerivation. While the +override mechanism above overrides the arguments of +a package function, overrideDerivation allows +changing the result of the function. This +permits changing any aspect of the package, such as the source code. +For instance, if you want to override the source code of Emacs, you +can say: + + +environment.systemPackages = + [ (pkgs.lib.overrideDerivation pkgs.emacs (attrs: { + name = "emacs-25.0-pre"; + src = /path/to/my/emacs/tree; + })) + ]; + + +Here, overrideDerivation takes the Nix derivation +specified by pkgs.emacs and produces a new +derivation in which the original’s name and +src attribute have been replaced by the given +values. The original attributes are accessible via +attrs. + +The overrides shown above are not global. They do not affect +the original package; other packages in Nixpkgs continue to depend on +the original rather than the customised package. This means that if +another package in your system depends on the original package, you +end up with two instances of the package. If you want to have +everything depend on your customised instance, you can apply a +global override as follows: + + +nixpkgs.config.packageOverrides = pkgs: + { emacs = pkgs.emacs.override { gtk = pkgs.gtk3; }; + }; + + +The effect of this definition is essentially equivalent to modifying +the emacs attribute in the Nixpkgs source tree. +Any package in Nixpkgs that depends on emacs will +be passed your customised instance. (However, the value +pkgs.emacs in +nixpkgs.config.packageOverrides refers to the +original rather than overriden instance, to prevent an infinite +recursion.) + +
+ +
Adding custom packages + +It’s possible that a package you need is not available in NixOS. +In that case, you can do two things. First, you can clone the Nixpkgs +repository, add the package to your clone, and (optionally) submit a +patch or pull request to have it accepted into the main Nixpkgs +repository. This is described in detail in the Nixpkgs manual. +In short, you clone Nixpkgs: + + +$ git clone git://github.com/NixOS/nixpkgs.git +$ cd nixpkgs + + +Then you write and test the package as described in the Nixpkgs +manual. Finally, you add it to +environment.systemPackages, e.g. + + +environment.systemPackages = [ pkgs.my-package ]; + + +and you run nixos-rebuild, specifying your own +Nixpkgs tree: + + +$ nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs + + + +The second possibility is to add the package outside of the +Nixpkgs tree. For instance, here is how you specify a build of the +GNU Hello +package directly in configuration.nix: + + +environment.systemPackages = + let + my-hello = with pkgs; stdenv.mkDerivation rec { + name = "hello-2.8"; + src = fetchurl { + url = "mirror://gnu/hello/${name}.tar.gz"; + sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6"; + }; + }; + in + [ my-hello ]; + + +Of course, you can also move the definition of +my-hello into a separate Nix expression, e.g. + +environment.systemPackages = [ (import ./my-hello.nix) ]; + +where my-hello.nix contains: + +with <nixpkgs> {}; # bring all of Nixpkgs into scope + +stdenv.mkDerivation rec { + name = "hello-2.8"; + src = fetchurl { + url = "mirror://gnu/hello/${name}.tar.gz"; + sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6"; + }; +} + + +This allows testing the package easily: + +$ nix-build my-hello.nix +$ ./result/bin/hello +Hello, world! + + + + +
+ +
+ + +
Ad hoc package management + +With the command nix-env, you can install and +uninstall packages from the command line. For instance, to install +Mozilla Thunderbird: + + +$ nix-env -iA nixos.pkgs.thunderbird + +If you invoke this as root, the package is installed in the Nix +profile /nix/var/nix/profiles/default and visible +to all users of the system; otherwise, the package ends up in +/nix/var/nix/profiles/per-user/username/profile +and is not visible to other users. The flag +specifies the package by its attribute name; without it, the package +is installed by matching against its package name +(e.g. thunderbird). The latter is slower because +it requires matching against all available Nix packages, and is +ambiguous if there are multiple matching packages. + +Packages come from the NixOS channel. You typically upgrade a +package by updating to the latest version of the NixOS channel: + +$ nix-channel --update nixos + +and then running nix-env -i again. Other packages +in the profile are not affected; this is the +crucial difference with the declarative style of package management, +where running nixos-rebuild switch causes all +packages to be updated to their current versions in the NixOS channel. +You can however upgrade all packages for which there is a newer +version by doing: + +$ nix-env -u '*' + + + +A package can be uninstalled using the +flag: + +$ nix-env -e thunderbird + + + +Finally, you can roll back an undesirable +nix-env action: + +$ nix-env --rollback + + + +nix-env has many more flags. For details, +see the +nix-env1 +manpage or the Nix manual. + +
+ + +
+ + + + +
User management + +NixOS supports both declarative and imperative styles of user +management. In the declarative style, users are specified in +configuration.nix. For instance, the following +states that a user account named alice shall exist: + + +users.extraUsers.alice = + { createHome = true; + home = "/home/alice"; + description = "Alice Foobar"; + extraGroups = [ "wheel" ]; + isSystemUser = false; + useDefaultShell = true; + openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ]; + }; + + +Note that alice is a member of the +wheel group, which allows her to use +sudo to execute commands as +root. Also note the SSH public key that allows +remote logins with the corresponding private key. Users created in +this way do not have a password by default, so they cannot log in via +mechanisms that require a password. However, you can use the +passwd program to set a password, which is retained +across invocations of nixos-rebuild. + +A user ID (uid) is assigned automatically. You can also specify +a uid manually by adding + + + uid = 1000; + + +to the user specification. + +Groups can be specified similarly. The following states that a +group named students shall exist: + + +users.extraGroups.students.gid = 1000; + + +As with users, the group ID (gid) is optional and will be assigned +automatically if it’s missing. + +Currently declarative user management is not perfect: +nixos-rebuild does not know how to realise certain +configuration changes. This includes removing a user or group, and +removing group membership from a user. + +In the imperative style, users and groups are managed by +commands such as useradd, +groupmod and so on. For instance, to create a user +account named alice: + + +$ useradd -m alice + +The flag causes the creation of a home directory +for the new user, which is generally what you want. The user does not +have an initial password and therefore cannot log in. A password can +be set using the passwd utility: + + +$ passwd alice +Enter new UNIX password: *** +Retype new UNIX password: *** + + +A user can be deleted using userdel: + + +$ userdel -r alice + +The flag deletes the user’s home directory. +Accounts can be modified using usermod. Unix +groups can be managed using groupadd, +groupmod and groupdel. + +
+ + + + +
File systems + +You can define file systems using the + configuration option. For instance, the +following definition causes NixOS to mount the Ext4 file system on +device /dev/disk/by-label/data onto the mount +point /data: + + +fileSystems."/data" = + { device = "/dev/disk/by-label/data"; + fsType = "ext4"; + }; + + +Mount points are created automatically if they don’t already exist. +For , it’s best to use the topology-independent +device aliases in /dev/disk/by-label and +/dev/disk/by-uuid, as these don’t change if the +topology changes (e.g. if a disk is moved to another IDE +controller). + +You can usually omit the file system type +(), since mount can usually +detect the type and load the necessary kernel module automatically. +However, if the file system is needed at early boot (in the initial +ramdisk) and is not ext2, ext3 +or ext4, then it’s best to specify + to ensure that the kernel module is +available. + +
LUKS-encrypted file systems + +NixOS supports file systems that are encrypted using +LUKS (Linux Unified Key Setup). For example, +here is how you create an encrypted Ext4 file system on the device +/dev/sda2: + + +$ cryptsetup luksFormat /dev/sda2 + +WARNING! +======== +This will overwrite data on /dev/sda2 irrevocably. + +Are you sure? (Type uppercase yes): YES +Enter LUKS passphrase: *** +Verify passphrase: *** + +$ cryptsetup luksOpen /dev/sda2 crypted +Enter passphrase for /dev/sda2: *** + +$ mkfs.ext4 /dev/mapper/crypted + + +To ensure that this file system is automatically mounted at boot time +as /, add the following to +configuration.nix: + + +boot.initrd.luks.devices = [ { device = "/dev/sda2"; name = "crypted"; } ]; +fileSystems."/".device = "/dev/mapper/crypted"; + + + + +
+ +
+ + + + +
X Window System + +The X Window System (X11) provides the basis of NixOS’ graphical +user interface. It can be enabled as follows: + +services.xserver.enable = true; + +The X server will automatically detect and use the appropriate video +driver from a set of X.org drivers (such as vesa +and intel). You can also specify a driver +manually, e.g. + +services.xserver.videoDrivers = [ "r128" ]; + +to enable X.org’s xf86-video-r128 driver. + +You also need to enable at least one desktop or window manager. +Otherwise, you can only log into a plain undecorated +xterm window. Thus you should pick one or more of +the following lines: + +services.xserver.desktopManager.kde4.enable = true; +services.xserver.desktopManager.xfce.enable = true; +services.xserver.windowManager.xmonad.enable = true; +services.xserver.windowManager.twm.enable = true; +services.xserver.windowManager.icewm.enable = true; + + + +NixOS’s default display manager (the +program that provides a graphical login prompt and manages the X +server) is SLiM. You can select KDE’s kdm instead: + +services.xserver.displayManager.kdm.enable = true; + + + +The X server is started automatically at boot time. If you +don’t want this to happen, you can set: + +services.xserver.autorun = false; + +The X server can then be started manually: + +$ systemctl start display-manager.service + + + + +
NVIDIA graphics cards + +NVIDIA provides a proprietary driver for its graphics cards that +has better 3D performance than the X.org drivers. It is not enabled +by default because it’s not free software. You can enable it as follows: + +services.xserver.videoDrivers = [ "nvidia" ]; + +You may need to reboot after enabling this driver to prevent a clash +with other kernel modules. + +On 64-bit systems, if you want full acceleration for 32-bit +programs such as Wine, you should also set the following: + +service.xserver.driSupport32Bit = true; + + + +
+ + +
Touchpads + +Support for Synaptics touchpads (found in many laptops such as +the Dell Latitude series) can be enabled as follows: + +services.xserver.synaptics.enable = true; + +The driver has many options (see ). For +instance, the following enables two-finger scrolling: + +services.xserver.synaptics.twoFingerScroll = true; + + + +
+ + +
+ + + + +
Networking + +
Secure shell access + +Secure shell (SSH) access to your machine can be enabled by +setting: + + +services.openssh.enable = true; + + +By default, root logins using a password are disallowed. They can be +disabled entirely by setting +services.openssh.permitRootLogin to +"no". + +You can declaratively specify authorised RSA/DSA public keys for +a user as follows: + + + +users.extraUsers.alice.openssh.authorizedKeys.keys = + [ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ]; + + + + +
+ + +
IPv4 configuration + +By default, NixOS uses DHCP (specifically, +dhcpcd) to automatically configure network +interfaces. However, you can configure an interface manually as +follows: + + +networking.interfaces.eth0 = { ipAddress = "192.168.1.2"; prefixLength = 24; }; + + +(The network prefix can also be specified using the option +subnetMask, +e.g. "255.255.255.0", but this is deprecated.) +Typically you’ll also want to set a default gateway and set of name +servers: + + +networking.defaultGateway = "192.168.1.1"; +networking.nameservers = [ "8.8.8.8" ]; + + + + +Statically configured interfaces are set up by the systemd +service +interface-name-cfg.service. +The default gateway and name server configuration is performed by +network-setup.service. + +The host name is set using : + + +networking.hostName = "cartman"; + + +The default host name is nixos. Set it to the +empty string ("") to allow the DHCP server to +provide the host name. + +
+ + +
IPv6 configuration + +IPv6 is enabled by default. Stateless address autoconfiguration +is used to automatically assign IPv6 addresses to all interfaces. You +can disable IPv6 support globally by setting: + + +networking.enableIPv6 = false; + + + + +
+ + +
Firewall + +NixOS has a simple stateful firewall that blocks incoming +connections and other unexpected packets. The firewall applies to +both IPv4 and IPv6 traffic. It can be enabled as follows: + + +networking.firewall.enable = true; + + +You can open specific TCP ports to the outside world: + + +networking.firewall.allowedTCPPorts = [ 80 443 ]; + + +Note that TCP port 22 (ssh) is opened automatically if the SSH daemon +is enabled (). UDP +ports can be opened through +. Also of +interest is + + +networking.firewall.allowPing = true; + + +to allow the machine to respond to ping requests. (ICMPv6 pings are +always allowed.) + +
+ + +
Wireless networks + + +NixOS will start wpa_supplicant for you if you enable this setting: + + +networking.wireless.enable = true; + + +NixOS currently does not generate wpa_supplicant's +configuration file, /etc/wpa_supplicant.conf. You should edit this file +yourself to define wireless networks, WPA keys and so on (see +wpa_supplicant.conf(5)). + + + +If you are using WPA2 the wpa_passphrase tool might be useful +to generate the wpa_supplicant.conf. + + +$ wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf + +After you have edited the wpa_supplicant.conf, +you need to restart the wpa_supplicant service. + + +$ systemctl restart wpa_supplicant.service + + + +
+ + +
Ad-hoc configuration + +You can use to specify +shell commands to be run at the end of +network-setup.service. This is useful for doing +network configuration not covered by the existing NixOS modules. For +instance, to statically configure an IPv6 address: + + +networking.localCommands = + '' + ip -6 addr add 2001:610:685:1::1/64 dev eth0 + ''; + + + + +
+ + + + + +
+ + + + +
Linux kernel + +You can override the Linux kernel and associated packages using +the option . For instance, this +selects the Linux 3.10 kernel: + +boot.kernelPackages = pkgs.linuxPackages_3_10; + +Note that this not only replaces the kernel, but also packages that +are specific to the kernel version, such as the NVIDIA video drivers. +This ensures that driver packages are consistent with the +kernel. + +The default Linux kernel configuration should be fine for most +users. You can see the configuration of your current kernel in +/run/booted-system/kernel-modules/config. If you +want to change the kernel configuration, you can use the + feature (see ). For instance, to enable +support for the kernel debugger KGDB: + + +nixpkgs.config.packageOverrides = pkgs: + { linux_3_4 = pkgs.linux_3_4.override { + extraConfig = + '' + KGDB y + ''; + }; + }; + + +extraConfig takes a list of Linux kernel +configuration options, one per line. The name of the option should +not include the prefix CONFIG_. The option value +is typically y, n or +m (to build something as a kernel module). + +Kernel modules for hardware devices are generally loaded +automatically by udev. You can force a module to +be loaded via , e.g. + +boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ]; + +If the module is required early during the boot (e.g. to mount the +root file system), you can use +: + +boot.initrd.extraKernelModules = [ "cifs" ]; + +This causes the specified modules and their dependencies to be added +to the initial ramdark. + +Kernel runtime parameters can be set through +, e.g. + +boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120; + +sets the kernel’s TCP keepalive time to 120 seconds. To see the +available parameters, run sysctl -a. + +
+ + + + + +
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix new file mode 100644 index 00000000000..db3245fcc07 --- /dev/null +++ b/nixos/doc/manual/default.nix @@ -0,0 +1,118 @@ +{ pkgs, options +, revision ? "master" +}: + +with pkgs.lib; + +let + + # Remove invisible and internal options. + options' = filter (opt: opt.visible && !opt.internal) (optionAttrSetToDocList options); + + # Clean up declaration sites to not refer to the NixOS source tree. + options'' = flip map options' (opt: opt // { + declarations = map (fn: stripPrefix fn) opt.declarations; + }); + + prefix = toString pkgs.path; + + stripPrefix = fn: + if substring 0 (stringLength prefix) fn == prefix then + substring (add (stringLength prefix) 1) 1000 fn + else + fn; + + optionsXML = builtins.toFile "options.xml" (builtins.unsafeDiscardStringContext (builtins.toXML options'')); + + optionsDocBook = pkgs.runCommand "options-db.xml" {} '' + if grep /nixpkgs/nixos/modules ${optionsXML}; then + echo "The manual appears to depend on the location of Nixpkgs, which is bad" + echo "since this prevents sharing via the NixOS channel. This is typically" + echo "caused by an option default that refers to a relative path (see above" + echo "for hints about the offending path)." + exit 1 + fi + ${pkgs.libxslt}/bin/xsltproc \ + --stringparam revision '${revision}' \ + -o $out ${./options-to-docbook.xsl} ${optionsXML} + ''; + +in rec { + + # Generate the NixOS manual. + manual = pkgs.stdenv.mkDerivation { + name = "nixos-manual"; + + sources = sourceFilesBySuffices ./. [".xml"]; + + buildInputs = [ pkgs.libxml2 pkgs.libxslt ]; + + xsltFlags = '' + --param section.autolabel 1 + --param section.label.includes.component.label 1 + --param html.stylesheet 'style.css' + --param xref.with.number.and.title 1 + --param toc.section.depth 3 + --param admon.style ''' + --param callout.graphics.extension '.gif' + ''; + + buildCommand = '' + ln -s $sources/*.xml . # */ + ln -s ${optionsDocBook} options-db.xml + + # Check the validity of the manual sources. + xmllint --noout --nonet --xinclude --noxincludenode \ + --relaxng ${pkgs.docbook5}/xml/rng/docbook/docbook.rng \ + manual.xml + + # Generate the HTML manual. + dst=$out/share/doc/nixos + ensureDir $dst + xsltproc $xsltFlags --nonet --xinclude \ + --output $dst/manual.html \ + ${pkgs.docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \ + ./manual.xml + + mkdir -p $dst/images/callouts + cp ${pkgs.docbook5_xsl}/xml/xsl/docbook/images/callouts/*.gif $dst/images/callouts/ + + cp ${./style.css} $dst/style.css + + mkdir -p $out/nix-support + echo "nix-build out $out" >> $out/nix-support/hydra-build-products + echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products + ''; # */ + + meta.description = "The NixOS manual in HTML format"; + }; + + # Generate the NixOS manpages. + manpages = pkgs.stdenv.mkDerivation { + name = "nixos-manpages"; + + sources = sourceFilesBySuffices ./. [".xml"]; + + buildInputs = [ pkgs.libxml2 pkgs.libxslt ]; + + buildCommand = '' + ln -s $sources/*.xml . # */ + ln -s ${optionsDocBook} options-db.xml + + # Check the validity of the manual sources. + xmllint --noout --nonet --xinclude --noxincludenode \ + --relaxng ${pkgs.docbook5}/xml/rng/docbook/docbook.rng \ + ./man-pages.xml + + # Generate manpages. + mkdir -p $out/share/man + xsltproc --nonet --xinclude \ + --param man.output.in.separate.dir 1 \ + --param man.output.base.dir "'$out/share/man/'" \ + --param man.endnotes.are.numbered 0 \ + ${pkgs.docbook5_xsl}/xml/xsl/docbook/manpages/docbook.xsl \ + ./man-pages.xml + ''; + }; + +} diff --git a/nixos/doc/manual/development.xml b/nixos/doc/manual/development.xml new file mode 100644 index 00000000000..6bbccac6e5c --- /dev/null +++ b/nixos/doc/manual/development.xml @@ -0,0 +1,853 @@ + + +Development + +This chapter describes how you can modify and extend +NixOS. + + + + +
+ +Getting the sources + +By default, NixOS’s nixos-rebuild command +uses the NixOS and Nixpkgs sources provided by the +nixos-unstable channel (kept in +/nix/var/nix/profiles/per-user/root/channels/nixos). +To modify NixOS, however, you should check out the latest sources from +Git. This is done using the following command: + + +$ nixos-checkout /my/sources + + +or + + +$ mkdir -p /my/sources +$ cd /my/sources +$ nix-env -i git +$ git clone git://github.com/NixOS/nixpkgs.git + + +This will check out the latest NixOS sources to +/my/sources/nixpkgs/nixos +and the Nixpkgs sources to +/my/sources/nixpkgs. +(The NixOS source tree lives in a subdirectory of the Nixpkgs +repository.) If you want to rebuild your system using your (modified) +sources, you need to tell nixos-rebuild about them +using the flag: + + +$ nixos-rebuild switch -I nixpkgs=/my/sources/nixpkgs + + + + +If you want nix-env to use the expressions in +/my/sources, use nix-env -f +/my/sources/nixpkgs, or change +the default by adding a symlink in +~/.nix-defexpr: + + +$ ln -s /my/sources/nixpkgs ~/.nix-defexpr/nixpkgs + + +You may want to delete the symlink +~/.nix-defexpr/channels_root to prevent root’s +NixOS channel from clashing with your own tree. + + + +
+ + + + +
+ +Writing NixOS modules + +NixOS has a modular system for declarative configuration. This +system combines multiple modules to produce the +full system configuration. One of the modules that constitute the +configuration is /etc/nixos/configuration.nix. +Most of the others live in the nixos/modules +subdirectory of the Nixpkgs tree. + +Each NixOS module is a file that handles one logical aspect of +the configuration, such as a specific kind of hardware, a service, or +network settings. A module configuration does not have to handle +everything from scratch; it can use the functionality provided by +other modules for its implementation. Thus a module can +declare options that can be used by other +modules, and conversely can define options +provided by other modules in its own implementation. For example, the +module pam.nix +declares the option that allows +other modules (e.g. sshd.nix) +to define PAM services; and it defines the option + (declared by etc.nix) +to cause files to be created in +/etc/pam.d. + +In , we saw the following structure +of NixOS modules: + + +{ config, pkgs, ... }: + +{ option definitions +} + + +This is actually an abbreviated form of module +that only defines options, but does not declare any. The structure of +full NixOS modules is shown in . + +Structure of NixOS modules + +{ config, pkgs, ... }: + +{ + imports = + [ paths of other modules + ]; + + options = { + option declarations + }; + + config = { + option definitions + }; +} + + +The meaning of each part is as follows. + + + + This line makes the current Nix expression a function. The + variable pkgs contains Nixpkgs, while + config contains the full system configuration. + This line can be omitted if there is no reference to + pkgs and config inside the + module. + + + + This list enumerates the paths to other NixOS modules that + should be included in the evaluation of the system configuration. + A default set of modules is defined in the file + modules/module-list.nix. These don't need to + be added in the import list. + + + + The attribute options is a nested set of + option declarations (described below). + + + + The attribute config is a nested set of + option definitions (also described + below). + + + + + + shows a module that handles +the regular update of the “locate” database, an index of all files in +the file system. This module declares two options that can be defined +by other modules (typically the user’s +configuration.nix): + (whether the database should +be updated) and (when the +update should be done). It implements its functionality by defining +two options declared by other modules: + (the set of all systemd services) +and (the list of +commands to be executed periodically by cron). + +NixOS module for the “locate” service + +{ config, pkgs, ... }: + +with pkgs.lib; + +let locatedb = "/var/cache/locatedb"; in + +{ + options = { + + services.locate = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + If enabled, NixOS will periodically update the database of + files used by the locate command. + ''; + }; + + period = mkOption { + type = types.str; + default = "15 02 * * *"; + description = '' + This option defines (in the format used by cron) when the + locate database is updated. The default is to update at + 02:15 at night every day. + ''; + }; + + }; + + }; + + config = { + + systemd.services.update-locatedb = + { description = "Update Locate Database"; + path = [ pkgs.su ]; + script = + '' + mkdir -m 0755 -p $(dirname ${locatedb}) + exec updatedb --localuser=nobody --output=${locatedb} --prunepaths='/tmp /var/tmp /media /run' + ''; + }; + + services.cron.systemCronJobs = optional config.services.locate.enable + "${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service"; + + }; +} + + +
Option declarations + +An option declaration specifies the name, type and description +of a NixOS configuration option. It is illegal to define an option +that hasn’t been declared in any module. A option declaration +generally looks like this: + + +options = { + name = mkOption { + type = type specification; + default = default value; + example = example value; + description = "Description for use in the NixOS manual."; + }; +}; + + + + +The function mkOption accepts the following arguments. + + + + + type + + The type of the option (see below). It may be omitted, + but that’s not advisable since it may lead to errors that are + hard to diagnose. + + + + + default + + The default value used if no value is defined by any + module. A default is not required; in that case, if the option + value is ever used, an error will be thrown. + + + + + example + + An example value that will be shown in the NixOS manual. + + + + + description + + A textual description of the option, in DocBook format, + that will be included in the NixOS manual. + + + + + + + +Here is a non-exhaustive list of option types: + + + + + types.bool + + A Boolean. + + + + + types.int + + An integer. + + + + + types.str + + A string. + + + + + types.lines + + A string. If there are multiple definitions, they are + concatenated, with newline characters in between. + + + + + types.path + + A path, defined as anything that, when coerced to a + string, starts with a slash. This includes derivations. + + + + + types.listOf t + + A list of elements of type t + (e.g., types.listOf types.str is a list of + strings). Multiple definitions are concatenated together. + + + + + types.attrsOf t + + A set of elements of type t + (e.g., types.attrsOf types.int is a set of + name/value pairs, the values being integers). + + + + + types.nullOr t + + Either the value null or something of + type t. + + + + + +You can also create new types using the function +mkOptionType. See +lib/types.nix in Nixpkgs for details. + +
+ + +
Option definitions + +Option definitions are generally straight-forward bindings of values to option names, like + + +config = { + services.httpd.enable = true; +}; + + +However, sometimes you need to wrap an option definition or set of +option definitions in a property to achieve +certain effects: + +Delaying conditionals + +If a set of option definitions is conditional on the value of +another option, you may need to use mkIf. +Consider, for instance: + + +config = if config.services.httpd.enable then { + environment.systemPackages = [ ... ]; + ... +} else {}; + + +This definition will cause Nix to fail with an “infinite recursion” +error. Why? Because the value of + depends on the value +being constructed here. After all, you could also write the clearly +circular and contradictory: + +config = if config.services.httpd.enable then { + services.httpd.enable = false; +} else { + services.httpd.enable = true; +}; + + +The solution is to write: + + +config = mkIf config.services.httpd.enable { + environment.systemPackages = [ ... ]; + ... +}; + + +The special function mkIf causes the evaluation of +the conditional to be “pushed down” into the individual definitions, +as if you had written: + + +config = { + environment.systemPackages = if config.services.httpd.enable then [ ... ] else []; + ... +}; + + + + + + +Setting priorities + +A module can override the definitions of an option in other +modules by setting a priority. All option +definitions that do not have the lowest priority value are discarded. +By default, option definitions have priority 1000. You can specify an +explicit priority by using mkOverride, e.g. + + +services.openssh.enable = mkOverride 10 false; + + +This definition causes all other definitions with priorities above 10 +to be discarded. The function mkForce is +equal to mkOverride 50. + + + +Merging configurations + +In conjunction with mkIf, it is sometimes +useful for a module to return multiple sets of option definitions, to +be merged together as if they were declared in separate modules. This +can be done using mkMerge: + + +config = mkMerge + [ # Unconditional stuff. + { environment.systemPackages = [ ... ]; + } + # Conditional stuff. + (mkIf config.services.bla.enable { + environment.systemPackages = [ ... ]; + }) + ]; + + + + + + +
+ + +
Important options + +NixOS has many options, but some are of particular importance to +module writers. + + + + + + + This set defines files in /etc. A + typical use is: + +environment.etc."os-release".text = + '' + NAME=NixOS + ... + ''; + + which causes a file named /etc/os-release + to be created with the given contents. + + + + + + + A set of shell script fragments that must be executed + whenever the configuration is activated (i.e., at boot time, or + after running nixos-rebuild switch). For instance, + +system.activationScripts.media = + '' + mkdir -m 0755 -p /media + ''; + + causes the directory /media to be created. + Activation scripts must be idempotent. They should not start + background processes such as daemons; use + for that. + + + + + + + This is the set of systemd services. Example: + +systemd.services.dhcpcd = + { description = "DHCP Client"; + wantedBy = [ "multi-user.target" ]; + after = [ "systemd-udev-settle.service" ]; + path = [ dhcpcd pkgs.nettools pkgs.openresolv ]; + serviceConfig = + { Type = "forking"; + PIDFile = "/run/dhcpcd.pid"; + ExecStart = "${dhcpcd}/sbin/dhcpcd --config ${dhcpcdConf}"; + Restart = "always"; + }; + }; + + which creates the systemd unit + dhcpcd.service. The option + determined which other units pull this + one in; multi-user.target is the default + target of the system, so dhcpcd.service will + always be started. The option + provides the main + command for the service; it’s also possible to provide pre-start + actions, stop scripts, and so on. + + + + + + + + If your service requires special UIDs or GIDs, you can + define them with these options. See for details. + + + + + +
+ + +
+ + + + +
+ +Building specific parts of NixOS + +With the command nix-build, you can build +specific parts of your NixOS configuration. This is done as follows: + + +$ cd /path/to/nixpkgs/nixos +$ nix-build -A config.option + +where option is a NixOS option with type +“derivation” (i.e. something that can be built). Attributes of +interest include: + + + + + system.build.toplevel + + The top-level option that builds the entire NixOS system. + Everything else in your configuration is indirectly pulled in by + this option. This is what nixos-rebuild + builds and what /run/current-system points + to afterwards. + + A shortcut to build this is: + + +$ nix-build -A system + + + + + + system.build.manual.manual + The NixOS manual. + + + + system.build.etc + A tree of symlinks that form the static parts of + /etc. + + + + system.build.initialRamdisk + system.build.kernel + + The initial ramdisk and kernel of the system. This allows + a quick way to test whether the kernel and the initial ramdisk + boot correctly, by using QEMU’s and + options: + + +$ nix-build -A config.system.build.initialRamdisk -o initrd +$ nix-build -A config.system.build.kernel -o kernel +$ qemu-system-x86_64 -kernel ./kernel/bzImage -initrd ./initrd/initrd -hda /dev/null + + + + + + + + system.build.nixos-rebuild + system.build.nixos-install + system.build.nixos-generate-config + + These build the corresponding NixOS commands. + + + + + + + +
+ + + + +
+ +Building your own NixOS CD + +Building a NixOS CD is as easy as configuring your own computer. The +idea is to use another module which will replace +your configuration.nix to configure the system that +would be installed on the CD. + +Default CD/DVD configurations are available +inside nixos/modules/installer/cd-dvd. To build them +you have to set NIXOS_CONFIG before +running nix-build to build the ISO. + + +$ nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd-dvd/installation-cd-minimal.nix + + + +Before burning your CD/DVD, you can check the content of the image by mounting anywhere like +suggested by the following command: + + +$ mount -o loop -t iso9660 ./result/iso/cd.iso /mnt/iso + + + +
+ + + + +
+ +Testing the installer + +Building, burning, and +booting from an installation CD is rather +tedious, so here is a quick way to see if the installer works +properly: + + +$ nix-build -A config.system.build.nixos-install +$ dd if=/dev/zero of=diskimage seek=2G count=0 bs=1 +$ yes | mke2fs -j diskimage +$ mount -o loop diskimage /mnt +$ ./result/bin/nixos-install + + + +
+ + + + + +
Whole-system testing using virtual machines + +Complete NixOS GNU/Linux systems can be tested in virtual +machines (VMs). This makes it possible to test a system upgrade or +configuration change before rebooting into it, using the +nixos-rebuild build-vm or nixos-rebuild +build-vm-with-bootloader command. + + +The tests/ directory in the NixOS source +tree contains several whole-system unit tests. +These tests can be runNixOS tests can be run both from +NixOS and from a non-NixOS GNU/Linux distribution, provided the Nix +package manager is installed. from the NixOS source +tree as follows: + + +$ nix-build tests/ -A nfs.test + + +This performs an automated test of the NFS client and server +functionality in the Linux kernel, including file locking semantics +(e.g., whether locks are maintained across server crashes). It will +first build or download all the dependencies of the test (e.g., all +packages needed to run a NixOS VM). The test is defined in +tests/nfs.nix. If the test succeeds, +nix-build will place a symlink +./result in the current directory pointing at the +location in the Nix store of the test results (e.g., screenshots, test +reports, and so on). In particular, a pretty-printed log of the test +is written to log.html, which can be viewed using +a web browser like this: + + +$ firefox result/log.html + + + +It is also possible to run the test environment interactively, +allowing you to experiment with the VMs. For example: + + +$ nix-build tests/ -A nfs.driver +$ ./result/bin/nixos-run-vms + + +The script nixos-run-vms starts the three virtual +machines defined in the NFS test using QEMU/KVM. The root file system +of the VMs is created on the fly and kept across VM restarts in +./hostname.qcow2. + +Finally, the test itself can be run interactively. This is +particularly useful when developing or debugging a test: + + +$ nix-build tests/ -A nfs.driver +$ ./result/bin/nixos-test-driver +starting VDE switch for network 1 +> + + +Perl statements can now be typed in to start or manipulate the VMs: + + +> startAll; +(the VMs start booting) +> $server->waitForJob("nfs-kernel-nfsd"); +> $client1->succeed("flock -x /data/lock -c 'sleep 100000' &"); +> $client2->fail("flock -n -s /data/lock true"); +> $client1->shutdown; +(this releases client1's lock) +> $client2->succeed("flock -n -s /data/lock true"); + + +The function testScript executes the entire test +script and drops you back into the test driver command line upon its +completion. This allows you to inspect the state of the VMs after the +test (e.g. to debug the test script). + +This and other tests are continuously run on the Hydra +instance at nixos.org, which allows +developers to be notified of any regressions introduced by a NixOS or +Nixpkgs change. + +The actual Nix programming interface to VM testing is in NixOS, +under +lib/testing.nix. This file defines a +function which takes an attribute set containing a +nixpkgs attribute (the path to a Nixpkgs checkout), +and a system attribute (the system type). It +returns an attribute set containing several utility functions, among +which the main entry point is makeTest. + + +The makeTest function takes a function +similar to that found in +tests/nfs.nix (discussed above). It +returns an attribute set containing (among others): + + + + + test + A derivation containing the test log as an HTML + file, as seen above, suitable for presentation in the Hydra + continuous build system. + + + + report + A derivation containing a code coverage report, with + meta-data suitable for Hydra. + + + + driver + A derivation containing scripts to run the VM test or + interact with the VM network interactively, as seen above. + + + + + + + +
+ + +
diff --git a/nixos/doc/manual/installation.xml b/nixos/doc/manual/installation.xml new file mode 100644 index 00000000000..88ef589dd06 --- /dev/null +++ b/nixos/doc/manual/installation.xml @@ -0,0 +1,469 @@ + + +Installing NixOS + + + + +
+ +Obtaining NixOS + +NixOS ISO images can be downloaded from the NixOS +homepage. These can be burned onto a CD. It is also possible +to copy them onto a USB stick and install NixOS from there. For +details, see the NixOS +Wiki. + +As an alternative to installing NixOS yourself, you can get a +running NixOS system through several other means: + + + + Using virtual appliances in Open Virtualization Format (OVF) + that can be imported into VirtualBox. These are available from + the NixOS + homepage. + + + Using AMIs for Amazon’s EC2. To find one for your region + and instance type, please refer to the list + of most recent AMIs. + + + Using NixOps, the NixOS-based cloud deployment tool, which + allows you to provision VirtualBox and EC2 NixOS instances from + declarative specifications. Check out the NixOps + homepage for details. + + + + + +
+ + + + +
+ +Installation + + + + Boot from the CD. + + The CD contains a basic NixOS installation. (It + also contains Memtest86+, useful if you want to test new hardware.) + When it’s finished booting, it should have detected most of your + hardware and brought up networking (check + ifconfig). Networking is necessary for the + installer, since it will download lots of stuff (such as source + tarballs or Nixpkgs channel binaries). It’s best if you have a DHCP + server on your network. Otherwise configure networking manually + using ifconfig. + + The NixOS manual is available on virtual console 8 + (press Alt+F8 to access). + + Login as root and the empty + password. + + If you downloaded the graphical ISO image, you can + run start display-manager to start KDE. + + The NixOS installer doesn’t do any partitioning or + formatting yet, so you need to that yourself. Use the following + commands: + + + + For partitioning: + fdisk. + + For initialising Ext4 partitions: + mkfs.ext4. It is recommended that you assign a + unique symbolic label to the file system using the option + , since this + makes the file system configuration independent from device + changes. For example: + + +$ mkfs.ext4 -L nixos /dev/sda1 + + + + For creating swap partitions: + mkswap. Again it’s recommended to assign a + label to the swap partition: . + + For creating LVM volumes, the LVM commands, e.g., + + +$ pvcreate /dev/sda1 /dev/sdb1 +$ vgcreate MyVolGroup /dev/sda1 /dev/sdb1 +$ lvcreate --size 2G --name bigdisk MyVolGroup +$ lvcreate --size 1G --name smalldisk MyVolGroup + + + + For creating software RAID devices, use + mdadm. + + + + + + Mount the target file system on which NixOS should + be installed on /mnt, e.g. + + +$ mount /dev/disk/by-label/nixos /mnt + + + + + If your machine has a limited amount of memory, you + may want to activate swap devices now (swapon + device). The installer (or + rather, the build actions that it may spawn) may need quite a bit of + RAM, depending on your configuration. + + + + You now need to create a file + /mnt/etc/nixos/configuration.nix that + specifies the intended configuration of the system. This is + because NixOS has a declarative configuration + model: you create or edit a description of the desired + configuration of your system, and then NixOS takes care of making + it happen. The syntax of the NixOS configuration file is + described in , while a + list of available configuration options appears in . A minimal example is shown in . + + The command nixos-generate-config can + generate an initial configuration file for you: + + +$ nixos-generate-config --root /mnt + + You should then edit + /mnt/etc/nixos/configuration.nix to suit your + needs: + + +$ nano /mnt/etc/nixos/configuration.nix + + + The vim text editor is also available. + + You must set the option + to specify on which disk + the GRUB boot loader is to be installed. Without it, NixOS cannot + boot. + + Another critical option is , + specifying the file systems that need to be mounted by NixOS. + However, you typically don’t need to set it yourself, because + nixos-generate-config sets it automatically in + /mnt/etc/nixos/hardware-configuration.nix + from your currently mounted file systems. (The configuration file + hardware-configuration.nix is included from + configuration.nix and will be overwritten by + future invocations of nixos-generate-config; + thus, you generally should not modify it.) + + Depending on your hardware configuration or type of + file system, you may need to set the option + to include the kernel + modules that are necessary for mounting the root file system, + otherwise the installed system will not be able to boot. (If this + happens, boot from the CD again, mount the target file system on + /mnt, fix + /mnt/etc/nixos/configuration.nix and rerun + nixos-install.) In most cases, + nixos-generate-config will figure out the + required modules. + + Examples of real-world NixOS configuration files can be + found at . + + + + Do the installation: + + +$ nixos-install + + Cross fingers. If this fails due to a temporary problem (such as + a network issue while downloading binaries from the NixOS binary + cache), you can just re-run nixos-install. + Otherwise, fix your configuration.nix and + then re-run nixos-install. + + If everything went well: + + +$ reboot + + + + + + You should now be able to boot into the installed NixOS. + The GRUB boot menu shows a list of available + configurations (initially just one). Every time you + change the NixOS configuration (see ), a new item appears in the menu. + This allows you to easily roll back to another configuration if + something goes wrong. + + You should log in and change the root + password with passwd. + + You’ll probably want to create some user accounts as well, + which can be done with useradd: + + +$ useradd -c 'Eelco Dolstra' -m eelco +$ passwd eelco + + + + You may also want to install some software. For instance, + + +$ nix-env -qa \* + + shows what packages are available, and + + +$ nix-env -i w3m + + install the w3m browser. + + + + + +To summarise, shows a +typical sequence of commands for installing NixOS on an empty hard +drive (here /dev/sda). shows a corresponding configuration Nix expression. + +Commands for installing NixOS on <filename>/dev/sda</filename> + +$ fdisk /dev/sda # (or whatever device you want to install on) +$ mkfs.ext4 -L nixos /dev/sda1 +$ mkswap -L swap /dev/sda2 +$ swapon /dev/sda2 +$ mount /dev/disk/by-label/nixos /mnt +$ nixos-generate-config --root /mnt +$ nano /mnt/etc/nixos/configuration.nix +$ nixos-install +$ reboot + + +NixOS configuration + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + boot.loader.grub.device = "/dev/sda"; + + # Note: setting fileSystems is generally not + # necessary, since nixos-generate-config figures them out + # automatically in hardware-configuration.nix. + #fileSystems."/".device = "/dev/disk/by-label/nixos"; + + # Enable the OpenSSH server. + services.sshd.enable = true; +} + + +
+ + + + + +
+ +Changing the configuration + +The file /etc/nixos/configuration.nix +contains the current configuration of your machine. Whenever you’ve +changed something to that file, you should do + + +$ nixos-rebuild switch + +to build the new configuration, make it the default configuration for +booting, and try to realise the configuration in the running system +(e.g., by restarting system services). + +These commands must be executed as root, so you should +either run them from a root shell or by prefixing them with +sudo -i. + +You can also do + + +$ nixos-rebuild test + +to build the configuration and switch the running system to it, but +without making it the boot default. So if (say) the configuration +locks up your machine, you can just reboot to get back to a working +configuration. + +There is also + + +$ nixos-rebuild boot + +to build the configuration and make it the boot default, but not +switch to it now (so it will only take effect after the next +reboot). + +You can make your configuration show up in a different submenu +of the GRUB 2 boot screen by giving it a different profile +name, e.g. + + +$ nixos-rebuild switch -p test + +which causes the new configuration (and previous ones created using +-p test) to show up in the GRUB submenu “NixOS - +Profile 'test'”. This can be useful to separate test configurations +from “stable” configurations. + +Finally, you can do + + +$ nixos-rebuild build + +to build the configuration but nothing more. This is useful to see +whether everything compiles cleanly. + +If you have a machine that supports hardware virtualisation, you +can also test the new configuration in a sandbox by building and +running a QEMU virtual machine that contains the +desired configuration. Just do + + +$ nixos-rebuild build-vm +$ ./result/bin/run-*-vm + + +The VM does not have use any data from your host system, so your +existing user accounts and home directories will not be +available. + +
+ + + + +
+ +Upgrading NixOS + +The best way to keep your NixOS installation up to date is to +use one of the NixOS channels. A channel is a +Nix mechanism for distributing Nix expressions and associated +binaries. The NixOS channels are updated automatically from NixOS’s +Git repository after certain tests have passed and all packages have +been built. These channels are: + + + + Stable channels, such as nixos-13.10. + These only get conservative bug fixes and package upgrades. For + instance, a channel update may cause the Linux kernel on your + system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but + not from 3.4.x to + 3.11.x (a major change that has the + potential to break things). Stable channels are generally + maintained until the next stable branch is created. + + + The unstable channel, nixos-unstable. + This corresponds to NixOS’s main development branch, and may thus + see radical changes between channel updates. It’s not recommended + for production systems. + + + +To see what channels are available, go to . (Note that the URIs of the +various channels redirect to a directory that contains the channel’s +latest version and includes ISO images and VirtualBox +appliances.) + +When you first install NixOS, you’re automatically subscribed to +the NixOS channel that corresponds to your installation source. For +instance, if you installed from a 13.10 ISO, you will be subscribed to +the nixos-13.10 channel. To see which NixOS +channel you’re subscribed to, run the following as root: + + +$ nix-channel --list | grep nixos +nixos https://nixos.org/channels/nixos-unstable + + +To switch to a different NixOS channel, do + + +$ nix-channel --add http://nixos.org/channels/channel-name nixos + + +(Be sure to include the nixos parameter at the +end.) For instance, to use the NixOS 13.10 stable channel: + + +$ nix-channel --add http://nixos.org/channels/nixos-13.10 nixos + + +But it you want to live on the bleeding edge: + + +$ nix-channel --add http://nixos.org/channels/nixos-unstable nixos + + + + +You can then upgrade NixOS to the latest version in your chosen +channel by running + + +$ nixos-rebuild switch --upgrade + + +which is equivalent to the more verbose nix-channel --update +nixos; nixos-rebuild switch. + +It is generally safe to switch back and forth between +channels. The only exception is that a newer NixOS may also have a +newer Nix version, which may involve an upgrade of Nix’s database +schema. This cannot be undone easily, so in that case you will not be +able to go back to your original channel. + +
+ +
diff --git a/nixos/doc/manual/man-configuration.xml b/nixos/doc/manual/man-configuration.xml new file mode 100644 index 00000000000..d49369d2c58 --- /dev/null +++ b/nixos/doc/manual/man-configuration.xml @@ -0,0 +1,38 @@ + + + + configuration.nix + 5 + NixOS + + + + + configuration.nix + NixOS system configuration specification + + + +Description + +The file /etc/nixos/configuration.nix +contains the declarative specification of your NixOS system +configuration. The command nixos-rebuild takes +this file and realises the system configuration specified +therein. + + + + +Options + +You can use the following options in +configuration.nix. + + + + + + diff --git a/nixos/doc/manual/man-nixos-build-vms.xml b/nixos/doc/manual/man-nixos-build-vms.xml new file mode 100644 index 00000000000..f37677629d0 --- /dev/null +++ b/nixos/doc/manual/man-nixos-build-vms.xml @@ -0,0 +1,110 @@ + + + + nixos-build-vms + 8 + NixOS + + + + + nixos-build-vms + build a network of virtual machines from a network of NixOS configurations + + + + + nixos-build-vms + + + + network.nix + + + +Description + +This command builds a network of QEMU-KVM virtual machines of a Nix expression +specifying a network of NixOS machines. The virtual network can be started by +executing the bin/run-vms shell script that is generated by +this command. By default, a result symlink is produced that +points to the generated virtual network. + + +A network Nix expression has the following structure: + + +{ + test1 = {pkgs, config, ...}: + { + services.openssh.enable = true; + nixpkgs.system = "i686-linux"; + deployment.targetHost = "test1.example.net"; + + # Other NixOS options + }; + + test2 = {pkgs, config, ...}: + { + services.openssh.enable = true; + services.httpd.enable = true; + environment.systemPackages = [ pkgs.lynx ]; + nixpkgs.system = "x86_64-linux"; + deployment.targetHost = "test2.example.net"; + + # Other NixOS options + }; +} + + +Each attribute in the expression represents a machine in the network +(e.g. test1 and test2) +referring to a function defining a NixOS configuration. +In each NixOS configuration, two attributes have a special meaning. +The deployment.targetHost specifies the address +(domain name or IP address) +of the system which is used by ssh to perform +remote deployment operations. The nixpkgs.system +attribute can be used to specify an architecture for the target machine, +such as i686-linux which builds a 32-bit NixOS +configuration. Omitting this property will build the configuration +for the same architecture as the host system. + + + + +Options + +This command accepts the following options: + + + + + + + Shows a trace of the output. + + + + + + + Do not create a 'result' symlink. + + + + + , + + Shows the usage of this command to the user. + + + + + + + + + diff --git a/nixos/doc/manual/man-nixos-generate-config.xml b/nixos/doc/manual/man-nixos-generate-config.xml new file mode 100644 index 00000000000..e4fba4a40a9 --- /dev/null +++ b/nixos/doc/manual/man-nixos-generate-config.xml @@ -0,0 +1,208 @@ + + + + nixos-generate-config + 8 + NixOS + + + + + nixos-generate-config + generate NixOS configuration modules + + + + + nixos-generate-config + + + + root + + + + dir + + + + + +Description + +This command writes two NixOS configuration modules: + + + + + + + This module sets NixOS configuration options based on your + current hardware configuration. In particular, it sets the + option to reflect all currently + mounted file systems, the option to + reflect active swap devices, and the + options to ensure that the + initial ramdisk contains any kernel modules necessary for + mounting the root file system. + + If this file already exists, it is overwritten. Thus, you + should not modify it manually. Rather, you should include it + from your /etc/nixos/configuration.nix, and + re-run nixos-generate-config to update it + whenever your hardware configuration changes. + + + + + + + This is the main NixOS system configuration module. If it + already exists, it’s left unchanged. Otherwise, + nixos-generate-config will write a template + for you to customise. + + + + + + + + + + +Options + +This command accepts the following options: + + + + + + + If this option is given, treat the directory + root as the root of the file system. + This means that configuration files will be written to + root/etc/nixos, + and that any file systems outside of + root are ignored for the purpose of + generating the option. + + + + + + + If this option is given, write the configuration files to + the directory dir instead of + /etc/nixos. + + + + + + + Overwrite + /etc/nixos/configuration.nix if it already + exists. + + + + + + + Omit everything concerning file system information + (which includes swap devices) from the hardware configuration. + + + + + + + Don't generate configuration.nix or + hardware-configuration.nix and print the + hardware configuration to stdout only. + + + + + + + + +Examples + +This command is typically used during NixOS installation to +write initial configuration modules. For example, if you created and +mounted the target file systems on /mnt and +/mnt/boot, you would run: + + +$ nixos-generate-config --root /mnt + + +The resulting file +/mnt/etc/nixos/hardware-configuration.nix might +look like this: + + +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, pkgs, ... }: + +{ + imports = + [ <nixos/modules/installer/scan/not-detected.nix> + ]; + + boot.initrd.availableKernelModules = [ "ehci_hcd" "ahci" ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-label/nixos"; + fsType = "ext3"; + options = "rw,data=ordered,relatime"; + }; + + fileSystems."/boot" = + { device = "/dev/sda1"; + fsType = "ext3"; + options = "rw,errors=continue,user_xattr,acl,barrier=1,data=writeback,relatime"; + }; + + swapDevices = + [ { device = "/dev/sda2"; } + ]; + + nix.maxJobs = 8; +} + + +It will also create a basic +/mnt/etc/nixos/configuration.nix, which you +should edit to customise the logical configuration of your system. +This file includes the result of the hardware scan as follows: + + + imports = [ ./hardware-configuration.nix ]; + + + +After installation, if your hardware configuration changes, you +can run: + + +$ nixos-generate-config + + +to update /etc/nixos/hardware-configuration.nix. +Your /etc/nixos/configuration.nix will +not be overwritten. + + + + diff --git a/nixos/doc/manual/man-nixos-install.xml b/nixos/doc/manual/man-nixos-install.xml new file mode 100644 index 00000000000..d5157859857 --- /dev/null +++ b/nixos/doc/manual/man-nixos-install.xml @@ -0,0 +1,78 @@ + + + + nixos-install + 8 + NixOS + + + + + nixos-install + install NixOS + + + + + nixos-install + + + + +Description + +This command installs NixOS in the file system mounted on +/mnt, based on the NixOS configuration specified +in /mnt/etc/nixos/configuration.nix. It performs +the following steps: + + + + It copies Nix and its dependencies to + /mnt/nix/store. + + It runs Nix in /mnt to build + the NixOS configuration specified in + /mnt/etc/nixos/configuration.nix. + + It installs the GRUB boot loader on the device + specified in the option , + and generates a GRUB configuration file that boots into the NixOS + configuration just installed. + + + + + +This command is idempotent: if it is interrupted or fails due to +a temporary problem (e.g. a network issue), you can safely re-run +it. + + + + +Examples + +A typical NixOS installation is done by creating and mounting a +file system on /mnt, generating a NixOS +configuration in +/mnt/etc/nixos/configuration.nix, and running +nixos-install. For instance, if we want to install +NixOS on an ext4 file system created in +/dev/sda1: + + +$ mkfs.ext4 /dev/sda1 +$ mount /dev/sda1 /mnt +$ nixos-generate-config --root /mnt +$ # edit /mnt/etc/nixos/configuration.nix +$ nixos-install + + + + + + + diff --git a/nixos/doc/manual/man-nixos-option.xml b/nixos/doc/manual/man-nixos-option.xml new file mode 100644 index 00000000000..7952847d4db --- /dev/null +++ b/nixos/doc/manual/man-nixos-option.xml @@ -0,0 +1,138 @@ + + + + nixos-option + 8 + NixOS + + + + + nixos-option + inspect a NixOS configuration + + + + + nixos-option + + + + + + option.name + + + + +Description + +This command evaluates the configuration specified in +/etc/nixos/configuration.nix and returns the properties +of the option name given as argument. By default, it returns the value of +the option. + +When the option name is not an option, the command prints the list of +attributes contained in the attribute set. + + + +Options + +This command accepts the following options: + + + + + , + + Returns the value of the option. This is the default operation + if no other options are defined. + + + + + , + + Return the default value, the example and the description of the + option when available. + + + + + , + + Return the locations where the option is declared and where it + is defined. This is extremely useful to find sources of errors in + your configuration. + + + + + + + + +Environment + + + + + NIXOS_CONFIG + + Path to the main NixOS configuration module. Defaults to + /etc/nixos/configuration.nix. + + + + + + + + +Examples + +Investigate option values: + +$ nixos-option boot.loader +This attribute set contains: +generationsDir +grub +initScript + +$ nixos-option boot.loader.grub.enable +true + +Prints option information: + +$ nixos-option -d networking.hostName +Default: "nixos" +Description: +The name of the machine. Leave it empty if you want to obtain +it from a DHCP server (if using DHCP). + +Find the locations which are declaring and defining an option: + +$ nixos-option -l hardware.firmware +Declared by: + /mnt/data/nix-sources/nixos/modules/services/hardware/udev.nix + +Defined by: + /path/to/nixpkgs/nixos/modules/system/boot/kernel.nix + /path/to/nixpkgs/nixos/modules/hardware/network/rt73.nix + /path/to/nixpkgs/nixos/modules/hardware/network/intel-3945abg.nix + /path/to/nixpkgs/nixos/modules/hardware/network/intel-2200bg.nix + + + +Bugs + +The author listed in the following section is wrong. If there is any + other bug, please report to Nicolas Pierron. + + + + + diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml new file mode 100644 index 00000000000..afc159dbd5d --- /dev/null +++ b/nixos/doc/manual/man-nixos-rebuild.xml @@ -0,0 +1,335 @@ + + + + nixos-rebuild + 8 + NixOS + + + + + nixos-rebuild + reconfigure a NixOS machine + + + + + nixos-rebuild + + + + + + + + + + + + + + + + + + + + + + name + + + + + + + +Description + +This command updates the system so that it corresponds to the +configuration specified in +/etc/nixos/configuration.nix. Thus, every time +you modify /etc/nixos/configuration.nix or any +NixOS module, you must run nixos-rebuild to make +the changes take effect. It builds the new system in +/nix/store, runs its activation script, and stop +and (re)starts any system services if needed. + +This command has one required argument, which specifies the +desired operation. It must be one of the following: + + + + + + + Build and activate the new configuration, and make it the + boot default. That is, the configuration is added to the GRUB + boot menu as the default meny entry, so that subsequent reboots + will boot the system into the new configuration. Previous + configurations activated with nixos-rebuild + switch or nixos-rebuild boot remain + available in the GRUB menu. + + + + + + + Build the new configuration and make it the boot default + (as with nixos-rebuild switch), but do not + activate it. That is, the system continues to run the previous + configuration until the next reboot. + + + + + + + Build and activate the new configuration, but do not add + it to the GRUB boot menu. Thus, if you reboot the system (or if + it crashes), you will automatically revert to the default + configuration (i.e. the configuration resulting from the last + call to nixos-rebuild switch or + nixos-rebuild boot). + + + + + + + Build the new configuration, but neither activate it nor + add it to the GRUB boot menu. It leaves a symlink named + result in the current directory, which + points to the output of the top-level “system” derivation. This + is essentially the same as doing + +$ nix-build /path/to/nixpkgs/nixos -A system + + Note that you do not need to be root to run + nixos-rebuild build. + + + + + + + Simply show what store paths would be built or downloaded + by any of the operations above. + + + + + + + Build a script that starts a NixOS virtual machine with + the desired configuration. It leaves a symlink + result in the current directory that points + (under + result/bin/run-hostname-vm) + at the script that starts the VM. Thus, to test a NixOS + configuration in a virtual machine, you should do the following: + +$ nixos-rebuild build-vm +$ ./result/bin/run-*-vm + + + The VM is implemented using the qemu + package. For best performance, you should load the + kvm-intel or kvm-amd + kernel modules to get hardware virtualisation. + + The VM mounts the Nix store of the host through the 9P + file system. The host Nix store is read-only, so Nix commands + that modify the Nix store will not work in the VM. This + includes commands such as nixos-rebuild; to + change the VM’s configuration, you must halt the VM and re-run + the commands above. + + + The VM has its own ext3 root file + system, which is automatically created when the VM is first + started, and is persistent across reboots of the VM. It is + stored in + ./hostname.qcow2. + + + + + + + + Like , but boots using the + regular boot loader of your configuration (e.g., GRUB 1 or 2), + rather than booting directly into the kernel and initial ramdisk + of the system. This allows you to test whether the boot loader + works correctly. However, it does not guarantee that your NixOS + configuration will boot successfully on the host hardware (i.e., + after running nixos-rebuild switch), because + the hardware and boot loader configuration in the VM are + different. The boot loader is installed on an automatically + generated virtual disk containing a /boot + partition, which is mounted read-only in the VM. + + + + + + + + + + + +Options + +This command accepts the following options: + + + + + + + Fetch the latest version of NixOS from the NixOS + channel. + + + + + + + Causes the GRUB boot loader to be (re)installed on the + device specified by the + boot.loader.grub.device configuration + option. + + + + + + + Normally, nixos-rebuild first builds + the nixUnstable attribute in Nixpkgs, and + uses the resulting instance of the Nix package manager to build + the new system configuration. This is necessary if the NixOS + modules use features not provided by the currently installed + version of Nix. This option disables building a new Nix. + + + + + + + Equivalent to + . This option is useful if you + call nixos-rebuild frequently (e.g. if you’re + hacking on a NixOS module). + + + + + + + Instead of building a new configuration as specified by + /etc/nixos/configuration.nix, roll back to + the previous configuration. (The previous configuration is + defined as the one before the “current” generation of the + Nix profile /nix/var/nix/profiles/system.) + + + + + + + + Instead of using the Nix profile + /nix/var/nix/profiles/system to keep track + of the current and previous system configurations, use + /nix/var/nix/profiles/system-profiles/name. + When you use GRUB 2, for every system profile created with this + flag, NixOS will create a submenu named “NixOS - Profile + 'name'” in GRUB’s boot menu, + containing the current and previous configurations of this + profile. + + For instance, if you want to test a configuration file + named test.nix without affecting the + default system profile, you would do: + + +$ nixos-rebuild switch -p test -I nixos-config=./test.nix + + + The new configuration will appear in the GRUB 2 submenu “NixOS - Profile + 'test'”. + + + + + +In addition, nixos-rebuild accepts various +Nix-related flags, including / +, , +, and + / . See +the Nix manual for details. + + + + +Environment + + + + + NIXOS_CONFIG + + Path to the main NixOS configuration module. Defaults to + /etc/nixos/configuration.nix. + + + + + + + + +Files + + + + + /run/current-system + + A symlink to the currently active system configuration in + the Nix store. + + + + + /nix/var/nix/profiles/system + + The Nix profile that contains the current and previous + system configurations. Used to generate the GRUB boot + menu. + + + + + + + + +Bugs + +This command should be renamed to something more +descriptive. + + + + + + diff --git a/nixos/doc/manual/man-pages.xml b/nixos/doc/manual/man-pages.xml new file mode 100644 index 00000000000..467864e208b --- /dev/null +++ b/nixos/doc/manual/man-pages.xml @@ -0,0 +1,31 @@ + + + NixOS Reference Pages + + + + + + Eelco + Dolstra + + Author + + + + 2007-2013 + Eelco Dolstra + + + + + + + + + + + + diff --git a/nixos/doc/manual/manual.xml b/nixos/doc/manual/manual.xml new file mode 100644 index 00000000000..dfbd865b505 --- /dev/null +++ b/nixos/doc/manual/manual.xml @@ -0,0 +1,62 @@ + + + + + NixOS Manual + + + + Eelco + Dolstra + + + + + + Nicolas + Pierron + + + + + 2007-2013 + Eelco Dolstra + + + + + + + Preface + + This manual describes how to install, use and extend NixOS, + a Linux distribution based on the purely functional package + management system Nix. + + If you encounter problems, please report them on the + nix-dev@lists.science.uu.nl + mailing list or on the + #nixos channel on Freenode. Bugs should + be reported in NixOS’ GitHub + issue tracker. + + + + + + + + + + + + List of options + + + + diff --git a/nixos/doc/manual/options-to-docbook.xsl b/nixos/doc/manual/options-to-docbook.xsl new file mode 100644 index 00000000000..6d11ad7a6c4 --- /dev/null +++ b/nixos/doc/manual/options-to-docbook.xsl @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default: + + + + + + + + Example: + + + + + + + + + + + + + + + Declared by: + + + + + + + Defined by: + + + + + + + + + + + + + + + + + + + +'' +'' + + + + + + + + + + null + + + + + + + '''' + + + "" + + + + + + + + + + + + true + + + + + false + + + + + [ + + + + + ] + + + + + + + + + + { + + + = + ; + + } + + + + + (build of ) + + + + + + + + + + + + https://github.com/NixOS/nixpkgs/blob/master/ + + + https://github.com/NixOS/nixpkgs/blob// + + + + + https://github.com/NixOS/nixops/blob//nix/ + + + file:// + + + + + + <nixpkgs/> + + + <nixops/> + + + + + + + + + + + diff --git a/nixos/doc/manual/running.xml b/nixos/doc/manual/running.xml new file mode 100644 index 00000000000..e50099707cc --- /dev/null +++ b/nixos/doc/manual/running.xml @@ -0,0 +1,369 @@ + + +Running NixOS + +This chapter describes various aspects of managing a running +NixOS system, such as how to use the systemd +service manager. + + + + +
Service management + +In NixOS, all system services are started and monitored using +the systemd program. Systemd is the “init” process of the system +(i.e. PID 1), the parent of all other processes. It manages a set of +so-called “units”, which can be things like system services +(programs), but also mount points, swap files, devices, targets +(groups of units) and more. Units can have complex dependencies; for +instance, one unit can require that another unit must be successfully +started before the first unit can be started. When the system boots, +it starts a unit named default.target; the +dependencies of this unit cause all system services to be started, +file systems to be mounted, swap files to be activated, and so +on. + +The command systemctl is the main way to +interact with systemd. Without any arguments, it +shows the status of active units: + + +$ systemctl +-.mount loaded active mounted / +swapfile.swap loaded active active /swapfile +sshd.service loaded active running SSH Daemon +graphical.target loaded active active Graphical Interface +... + + + + +You can ask for detailed status information about a unit, for +instance, the PostgreSQL database service: + + +$ systemctl status postgresql.service +postgresql.service - PostgreSQL Server + Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service) + Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago + Main PID: 2390 (postgres) + CGroup: name=systemd:/system/postgresql.service + ├─2390 postgres + ├─2418 postgres: writer process + ├─2419 postgres: wal writer process + ├─2420 postgres: autovacuum launcher process + ├─2421 postgres: stats collector process + └─2498 postgres: zabbix zabbix [local] idle + +Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG: database system was shut down at 2013-01-07 15:55:05 CET +Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG: database system is ready to accept connections +Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG: autovacuum launcher started +Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server. + + +Note that this shows the status of the unit (active and running), all +the processes belonging to the service, as well as the most recent log +messages from the service. + + + +Units can be stopped, started or restarted: + + +$ systemctl stop postgresql.service +$ systemctl start postgresql.service +$ systemctl restart postgresql.service + + +These operations are synchronous: they wait until the service has +finished starting or stopping (or has failed). Starting a unit will +cause the dependencies of that unit to be started as well (if +necessary). + + + +
+ + + + +
Rebooting and shutting down + +The system can be shut down (and automatically powered off) by +doing: + + +$ shutdown + + +This is equivalent to running systemctl +poweroff. + +To reboot the system, run + + +$ reboot + + +which is equivalent to systemctl reboot. +Alternatively, you can quickly reboot the system using +kexec, which bypasses the BIOS by directly loading +the new kernel into memory: + + +$ systemctl kexec + + + + +The machine can be suspended to RAM (if supported) using +systemctl suspend, and suspended to disk using +systemctl hibernate. + +These commands can be run by any user who is logged in locally, +i.e. on a virtual console or in X11; otherwise, the user is asked for +authentication. + +
+ + + + +
User sessions + +Systemd keeps track of all users who are logged into the system +(e.g. on a virtual console or remotely via SSH). The command +loginctl allows querying and manipulating user +sessions. For instance, to list all user sessions: + + +$ loginctl + SESSION UID USER SEAT + c1 500 eelco seat0 + c3 0 root seat0 + c4 500 alice + + +This shows that two users are logged in locally, while another is +logged in remotely. (“Seats” are essentially the combinations of +displays and input devices attached to the system; usually, there is +only one seat.) To get information about a session: + + +$ loginctl session-status c3 +c3 - root (0) + Since: Tue, 2013-01-08 01:17:56 CET; 4min 42s ago + Leader: 2536 (login) + Seat: seat0; vc3 + TTY: /dev/tty3 + Service: login; type tty; class user + State: online + CGroup: name=systemd:/user/root/c3 + ├─ 2536 /nix/store/10mn4xip9n7y9bxqwnsx7xwx2v2g34xn-shadow-4.1.5.1/bin/login -- + ├─10339 -bash + └─10355 w3m nixos.org + + +This shows that the user is logged in on virtual console 3. It also +lists the processes belonging to this session. Since systemd keeps +track of this, you can terminate a session in a way that ensures that +all the session’s processes are gone: + + +$ loginctl terminate-session c3 + + + + +
+ + + + +
Control groups + +To keep track of the processes in a running system, systemd uses +control groups (cgroups). A control group is a +set of processes used to allocate resources such as CPU, memory or I/O +bandwidth. There can be multiple control group hierarchies, allowing +each kind of resource to be managed independently. + +The command systemd-cgls lists all control +groups in the systemd hierarchy, which is what +systemd uses to keep track of the processes belonging to each service +or user session: + + +$ systemd-cgls +├─user +│ └─eelco +│ └─c1 +│ ├─ 2567 -:0 +│ ├─ 2682 kdeinit4: kdeinit4 Running... +│ ├─ ... +│ └─10851 sh -c less -R +└─system + ├─httpd.service + │ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH + │ └─... + ├─dhcpcd.service + │ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf + └─ ... + + +Similarly, systemd-cgls cpu shows the cgroups in +the CPU hierarchy, which allows per-cgroup CPU scheduling priorities. +By default, every systemd service gets its own CPU cgroup, while all +user sessions are in the top-level CPU cgroup. This ensures, for +instance, that a thousand run-away processes in the +httpd.service cgroup cannot starve the CPU for one +process in the postgresql.service cgroup. (By +contrast, it they were in the same cgroup, then the PostgreSQL process +would get 1/1001 of the cgroup’s CPU time.) You can limit a service’s +CPU share in configuration.nix: + + +systemd.services.httpd.serviceConfig.CPUShares = 512; + + +By default, every cgroup has 1024 CPU shares, so this will halve the +CPU allocation of the httpd.service cgroup. + +There also is a memory hierarchy that +controls memory allocation limits; by default, all processes are in +the top-level cgroup, so any service or session can exhaust all +available memory. Per-cgroup memory limits can be specified in +configuration.nix; for instance, to limit +httpd.service to 512 MiB of RAM (excluding swap) +and 640 MiB of RAM (including swap): + + +systemd.services.httpd.serviceConfig.MemoryLimit = "512M"; +systemd.services.httpd.serviceConfig.ControlGroupAttribute = [ "memory.memsw.limit_in_bytes 640M" ]; + + + + +The command systemd-cgtop shows a +continuously updated list of all cgroups with their CPU and memory +usage. + +
+ + + + +
Logging + +System-wide logging is provided by systemd’s +journal, which subsumes traditional logging +daemons such as syslogd and klogd. Log entries are kept in binary +files in /var/log/journal/. The command +journalctl allows you to see the contents of the +journal. For example, + + +$ journalctl -b + + +shows all journal entries since the last reboot. (The output of +journalctl is piped into less by +default.) You can use various options and match operators to restrict +output to messages of interest. For instance, to get all messages +from PostgreSQL: + + +$ journalctl -u postgresql.service +-- Logs begin at Mon, 2013-01-07 13:28:01 CET, end at Tue, 2013-01-08 01:09:57 CET. -- +... +Jan 07 15:44:14 hagbard postgres[2681]: [2-1] LOG: database system is shut down +-- Reboot -- +Jan 07 15:45:10 hagbard postgres[2532]: [1-1] LOG: database system was shut down at 2013-01-07 15:44:14 CET +Jan 07 15:45:13 hagbard postgres[2500]: [1-1] LOG: database system is ready to accept connections + + +Or to get all messages since the last reboot that have at least a +“critical” severity level: + + +$ journalctl -b -p crit +Dec 17 21:08:06 mandark sudo[3673]: pam_unix(sudo:auth): auth could not identify password for [alice] +Dec 29 01:30:22 mandark kernel[6131]: [1053513.909444] CPU6: Core temperature above threshold, cpu clock throttled (total events = 1) + + + + +The system journal is readable by root and by users in the +wheel and systemd-journal +groups. All users have a private journal that can be read using +journalctl. + +
+ + + + +
Cleaning up the Nix store + +Nix has a purely functional model, meaning that packages are +never upgraded in place. Instead new versions of packages end up in a +different location in the Nix store (/nix/store). +You should periodically run Nix’s garbage +collector to remove old, unreferenced packages. This is +easy: + + +$ nix-collect-garbage + + +Alternatively, you can use a systemd unit that does the same in the +background: + + +$ systemctl start nix-gc.service + + +You can tell NixOS in configuration.nix to run +this unit automatically at certain points in time, for instance, every +night at 03:15: + + +nix.gc.automatic = true; +nix.gc.dates = "03:15"; + + + + +The commands above do not remove garbage collector roots, such +as old system configurations. Thus they do not remove the ability to +roll back to previous configurations. The following command deletes +old roots, removing the ability to roll back to them: + +$ nix-collect-garbage -d + +You can also do this for specific profiles, e.g. + +$ nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old + +Note that NixOS system configurations are stored in the profile +/nix/var/nix/profiles/system. + +Another way to reclaim disk space (often as much as 40% of the +size of the Nix store) is to run Nix’s store optimiser, which seeks +out identical files in the store and replaces them with hard links to +a single copy. + +$ nix-store --optimise + +Since this command needs to read the entire Nix store, it can take +quite a while to finish. + +
+ + +
diff --git a/nixos/doc/manual/style.css b/nixos/doc/manual/style.css new file mode 100644 index 00000000000..e2204c159e2 --- /dev/null +++ b/nixos/doc/manual/style.css @@ -0,0 +1,268 @@ +/* Copied from http://bakefile.sourceforge.net/, which appears + licensed under the GNU GPL. */ + + +/*************************************************************************** + Basic headers and text: + ***************************************************************************/ + +body +{ + font-family: "Nimbus Sans L", sans-serif; + background: white; + margin: 2em 1em 2em 1em; +} + +h1, h2, h3, h4 +{ + color: #005aa0; +} + +h1 /* title */ +{ + font-size: 200%; +} + +h2 /* chapters, appendices, subtitle */ +{ + font-size: 180%; +} + +/* Extra space between chapters, appendices. */ +div.chapter > div.titlepage h2, div.appendix > div.titlepage h2 +{ + margin-top: 1.5em; +} + +div.section > div.titlepage h2 /* sections */ +{ + font-size: 150%; + margin-top: 1.5em; +} + +h3 /* subsections */ +{ + font-size: 125%; +} + +div.simplesect h2 +{ + font-size: 110%; +} + +div.appendix h3 +{ + font-size: 150%; + margin-top: 1.5em; +} + +div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */ +{ + margin-top: 1.4em; + font-size: 125%; +} + +div.refsection h3 +{ + font-size: 110%; +} + + +/*************************************************************************** + Examples: + ***************************************************************************/ + +div.example +{ + border: 1px solid #b0b0b0; + padding: 6px 6px; + margin-left: 1.5em; + margin-right: 1.5em; + background: #f4f4f8; + border-radius: 0.4em; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +div.example p.title +{ + margin-top: 0em; +} + +div.example pre +{ + box-shadow: none; +} + + +/*************************************************************************** + Screen dumps: + ***************************************************************************/ + +pre.screen, pre.programlisting +{ + border: 1px solid #b0b0b0; + padding: 3px 3px; + margin-left: 1.5em; + margin-right: 1.5em; + color: #600000; + background: #f4f4f8; + font-family: monospace; + border-radius: 0.4em; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +div.example pre.programlisting +{ + border: 0px; + padding: 0 0; + margin: 0 0 0 0; +} + + +/*************************************************************************** + Notes, warnings etc: + ***************************************************************************/ + +.note, .warning +{ + border: 1px solid #b0b0b0; + padding: 3px 3px; + margin-left: 1.5em; + margin-right: 1.5em; + margin-bottom: 1em; + padding: 0.3em 0.3em 0.3em 0.3em; + background: #fffff5; + border-radius: 0.4em; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +div.note, div.warning +{ + font-style: italic; +} + +div.note h3, div.warning h3 +{ + color: red; + font-size: 100%; + padding-right: 0.5em; + display: inline; +} + +div.note p, div.warning p +{ + margin-bottom: 0em; +} + +div.note h3 + p, div.warning h3 + p +{ + display: inline; +} + +div.note h3 +{ + color: blue; + font-size: 100%; +} + +div.navfooter * +{ + font-size: 90%; +} + + +/*************************************************************************** + Links colors and highlighting: + ***************************************************************************/ + +a { text-decoration: none; } +a:hover { text-decoration: underline; } +a:link { color: #0048b3; } +a:visited { color: #002a6a; } + + +/*************************************************************************** + Table of contents: + ***************************************************************************/ + +div.toc +{ + font-size: 90%; +} + +div.toc dl +{ + margin-top: 0em; + margin-bottom: 0em; +} + + +/*************************************************************************** + Special elements: + ***************************************************************************/ + +tt, code +{ + color: #400000; +} + +.term +{ + font-weight: bold; + +} + +div.variablelist dd p, div.glosslist dd p +{ + margin-top: 0em; +} + +div.variablelist dd, div.glosslist dd +{ + margin-left: 1.5em; +} + +div.glosslist dt +{ + font-style: italic; +} + +.varname +{ + color: #400000; +} + +span.command strong +{ + font-weight: normal; + color: #400000; +} + +div.calloutlist table +{ + box-shadow: none; +} + +table +{ + border-collapse: collapse; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +table.simplelist +{ + text-align: left; + color: #005aa0; + border: 0; + padding: 5px; + background: #fffff5; + font-weight: normal; + font-style: italic; + box-shadow: none; + margin-bottom: 1em; +} + +div.affiliation +{ + font-style: italic; +} \ No newline at end of file diff --git a/nixos/doc/manual/troubleshooting.xml b/nixos/doc/manual/troubleshooting.xml new file mode 100644 index 00000000000..c6e0a3a7888 --- /dev/null +++ b/nixos/doc/manual/troubleshooting.xml @@ -0,0 +1,198 @@ + + +Troubleshooting + + + + +
Boot problems + +If NixOS fails to boot, there are a number of kernel command +line parameters that may help you to identify or fix the issue. You +can add these parameters in the GRUB boot menu by pressing “e” to +modify the selected boot entry and editing the line starting with +linux. The following are some useful kernel command +line parameters that are recognised by the NixOS boot scripts or by +systemd: + + + + boot.shell_on_fail + Start a root shell if something goes wrong in + stage 1 of the boot process (the initial ramdisk). This is + disabled by default because there is no authentication for the + root shell. + + + boot.debug1 + Start an interactive shell in stage 1 before + anything useful has been done. That is, no modules have been + loaded and no file systems have been mounted, except for + /proc and + /sys. + + + boot.trace + Print every shell command executed by the stage 1 + and 2 boot scripts. + + + single + Boot into rescue mode (a.k.a. single user mode). + This will cause systemd to start nothing but the unit + rescue.target, which runs + sulogin to prompt for the root password and + start a root login shell. Exiting the shell causes the system to + continue with the normal boot process. + + + systemd.log_level=debug systemd.log_target=console + Make systemd very verbose and send log messages to + the console instead of the journal. + + + + +For more parameters recognised by systemd, see +systemd1. + +If no login prompts or X11 login screens appear (e.g. due to +hanging dependencies), you can press Alt+ArrowUp. If you’re lucky, +this will start rescue mode (described above). (Also note that since +most units have a 90-second timeout before systemd gives up on them, +the agetty login prompts should appear eventually +unless something is very wrong.) + +
+ + + + +
Maintenance mode + +You can enter rescue mode by running: + + +$ systemctl rescue + +This will eventually give you a single-user root shell. Systemd will +stop (almost) all system services. To get out of maintenance mode, +just exit from the rescue shell. + +
+ + + + +
Rolling back configuration changes + +After running nixos-rebuild to switch to a +new configuration, you may find that the new configuration doesn’t +work very well. In that case, there are several ways to return to a +previous configuration. + +First, the GRUB boot manager allows you to boot into any +previous configuration that hasn’t been garbage-collected. These +configurations can be found under the GRUB submenu “NixOS - All +configurations”. This is especially useful if the new configuration +fails to boot. After the system has booted, you can make the selected +configuration the default for subsequent boots: + + +$ /run/current-system/bin/switch-to-configuration boot + + + +Second, you can switch to the previous configuration in a running +system: + + +$ nixos-rebuild switch --rollback + +This is equivalent to running: + + +$ /nix/var/nix/profiles/system-N-link/bin/switch-to-configuration switch + +where N is the number of the NixOS system +configuration. To get a list of the available configurations, do: + + +$ ls -l /nix/var/nix/profiles/system-*-link +... +lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055 + + + + +
+ + + + +
Nix store corruption + +After a system crash, it’s possible for files in the Nix store +to become corrupted. (For instance, the Ext4 file system has the +tendency to replace un-synced files with zero bytes.) NixOS tries +hard to prevent this from happening: it performs a +sync before switching to a new configuration, and +Nix’s database is fully transactional. If corruption still occurs, +you may be able to fix it automatically. + +If the corruption is in a path in the closure of the NixOS +system configuration, you can fix it by doing + + +$ nixos-rebuild switch --repair + + +This will cause Nix to check every path in the closure, and if its +cryptographic hash differs from the hash recorded in Nix’s database, +the path is rebuilt or redownloaded. + +You can also scan the entire Nix store for corrupt paths: + + +$ nix-store --verify --check-contents --repair + + +Any corrupt paths will be redownloaded if they’re available in a +binary cache; otherwise, they cannot be repaired. + +
+ + + + +
Nix network issues + +Nix uses a so-called binary cache to +optimise building a package from source into downloading it as a +pre-built binary. That is, whenever a command like +nixos-rebuild needs a path in the Nix store, Nix +will try to download that path from the Internet rather than build it +from source. The default binary cache is +http://cache.nixos.org/. If this cache is unreachable, Nix +operations may take a long time due to HTTP connection timeouts. You +can disable the use of the binary cache by adding , e.g. + + +$ nixos-rebuild switch --option use-binary-caches false + + +If you have an alternative binary cache at your disposal, you can use +it instead: + + +$ nixos-rebuild switch --option binary-caches http://my-cache.example.org/ + + + + +
+ + +
diff --git a/nixos/gui/README b/nixos/gui/README new file mode 100644 index 00000000000..c038314a0dc --- /dev/null +++ b/nixos/gui/README @@ -0,0 +1,16 @@ +This file should become a nix expression. (see modules/installer/tools/tools.nix) + +you need to: +- download the latest jQuery from and copy it to chrome/content: + http://code.jquery.com/jquery-1.5.2.js + +- install 'xulrunner' with nix: + nix-env -Ai nixpkgs_sys.firefox40Pkgs.xulrunner + +- make sure nixos-option in your path + +- have /etc/nixos/nixpkgs +- have /etc/nixos/nixos + +run it: +- xulrunner /etc/nixos/nixos/gui/application.ini -jsconsole diff --git a/nixos/gui/application.ini b/nixos/gui/application.ini new file mode 100644 index 00000000000..d2494a1a5cd --- /dev/null +++ b/nixos/gui/application.ini @@ -0,0 +1,36 @@ +[App] +; +; This field specifies your organization's name. This field is recommended, +; but optional. +Vendor=NixOS +; +; This field specifies your application's name. This field is required. +Name=NixOS-gui +; +; This field specifies your application's version. This field is optional. +Version=0.1 +; +; This field specifies your application's build ID (timestamp). This field is +; required. +BuildID=20110424 +; +; This field specifies a compact copyright notice for your application. This +; field is optional. +;Copyright= + +; +; This ID is just an example. Every XUL app ought to have it's own unique ID. +; You can use the microsoft "guidgen" or "uuidgen" tools, or go on +; irc.mozilla.org and /msg botbot uuid. This field is optional. +;ID= + +[Gecko] +; +; This field is required. It specifies the minimum Gecko version that this +; application requires. +MinVersion=1.9a5 +; +; This field is optional. It specifies the maximum Gecko version that this +; application requires. It should be specified if your application uses +; unfrozen interfaces. +MaxVersion=2.* diff --git a/nixos/gui/chrome.manifest b/nixos/gui/chrome.manifest new file mode 100644 index 00000000000..865d6a88fb4 --- /dev/null +++ b/nixos/gui/chrome.manifest @@ -0,0 +1 @@ +manifest chrome/chrome.manifest diff --git a/nixos/gui/chrome/chrome.manifest b/nixos/gui/chrome/chrome.manifest new file mode 100644 index 00000000000..775445ee17b --- /dev/null +++ b/nixos/gui/chrome/chrome.manifest @@ -0,0 +1 @@ +content nixos-gui content/ diff --git a/nixos/gui/chrome/content/io.js b/nixos/gui/chrome/content/io.js new file mode 100644 index 00000000000..8d9c8c17365 --- /dev/null +++ b/nixos/gui/chrome/content/io.js @@ -0,0 +1,137 @@ + +function inspect(obj, maxLevels, level) +{ + var str = '', type, msg; + + // Start Input Validations + // Don't touch, we start iterating at level zero + if(level == null) level = 0; + + // At least you want to show the first level + if(maxLevels == null) maxLevels = 1; + if(maxLevels < 1) + return 'Error: Levels number must be > 0'; + + // We start with a non null object + if(obj == null) + return 'Error: Object NULL'; + // End Input Validations + + // Each Iteration must be indented + str += '
    '; + + // Start iterations for all objects in obj + for(property in obj) + { + try + { + // Show "property" and "type property" + type = typeof(obj[property]); + str += '
  • (' + type + ') ' + property + + ( (obj[property]==null)?(': null'):('')) + '
  • '; + + // We keep iterating if this property is an Object, non null + // and we are inside the required number of levels + if((type == 'object') && (obj[property] != null) && (level+1 < maxLevels)) + str += inspect(obj[property], maxLevels, level+1); + } + catch(err) + { + // Is there some properties in obj we can't access? Print it red. + if(typeof(err) == 'string') msg = err; + else if(err.message) msg = err.message; + else if(err.description) msg = err.description; + else msg = 'Unknown'; + + str += '
  • (Error) ' + property + ': ' + msg +'
  • '; + } + } + + // Close indent + str += '
'; + + return str; +} + +// Run xulrunner application.ini -jsconsole -console, to see messages. +function log(str) +{ + Components.classes['@mozilla.org/consoleservice;1'] + .getService(Components.interfaces.nsIConsoleService) + .logStringMessage(str); +} + +function makeTempFile(prefix) +{ + var file = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties) + .get("TmpD", Components.interfaces.nsIFile); + file.append(prefix || "xulrunner"); + file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664); + return file; +} + +function writeToFile(file, data) +{ + // file is nsIFile, data is a string + var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"] + .createInstance(Components.interfaces.nsIFileOutputStream); + + // use 0x02 | 0x10 to open file for appending. + foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate + foStream.write(data, data.length); + foStream.close(); +} + +function readFromFile(file) +{ + // |file| is nsIFile + var data = ""; + var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"] + .createInstance(Components.interfaces.nsIFileInputStream); + var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"] + .createInstance(Components.interfaces.nsIScriptableInputStream); + fstream.init(file, -1, 0, 0); + sstream.init(fstream); + + var str = sstream.read(4096); + while (str.length > 0) { + data += str; + str = sstream.read(4096); + } + + sstream.close(); + fstream.close(); + + return data; +} + +function runProgram(commandLine) +{ + // create an nsILocalFile for the executable + var file = Components.classes["@mozilla.org/file/local;1"] + .createInstance(Components.interfaces.nsILocalFile); + file.initWithPath("/bin/sh"); + + // create an nsIProcess + var process = Components.classes["@mozilla.org/process/util;1"] + .createInstance(Components.interfaces.nsIProcess); + process.init(file); + + // Run the process. + // If first param is true, calling thread will be blocked until + // called process terminates. + // Second and third params are used to pass command-line arguments + // to the process. + var args = ["-c", commandLine]; + process.run(true, args, args.length); +} + +// only for testing... +function testIO() +{ + var f = makeTempFile(); + writeToFile(f, "essai\ntest"); + alert(readFromFile(f)); + runProgram("zenity --info"); +} diff --git a/nixos/gui/chrome/content/main.js b/nixos/gui/chrome/content/main.js new file mode 100644 index 00000000000..ecfc5a8c5c9 --- /dev/null +++ b/nixos/gui/chrome/content/main.js @@ -0,0 +1,70 @@ +// global variables. +var gNixOS; +var gOptionView; + +/* +var gProgressBar; +function setProgress(current, max) +{ + if (gProgressBar) { + gProgressBar.value = 100 * current / max; + log("progress: " + gProgressBar.value + "%"); + } + else + log("unknow progress bar"); +} +*/ + +function updateTextbox(id, value) +{ + // setting the height cause an overflow which resize the textbox to its + // content due to its onoverflow attribute. + $(id).attr("value", value).attr("height", 1); +}; + +function updatePanel(options) +{ + log("updatePanel: " + options.length); + if (options.length == 0) + return; + // FIXME: ignore the rest of the selection for now. + var o = options[0]; + $("#name").attr("label", o.path); + + if (o.typename != null) + $("#typename").attr("label", o.typename); + else + $("#typename").attr("label", ""); + + $("#desc").text(o.description); + + if (o.value != null) + updateTextbox("#val", o.value); + else + updateTextbox("#val", ""); + + if (o.defaultValue != null) + updateTextbox("#def", o.defaultValue); + else + updateTextbox("#def", ""); + + if (o.example != null) + updateTextbox("#exp", o.example); + else + updateTextbox("#exp", ""); + + updateTextbox("#decls", o.declarations.join("\n")); + updateTextbox("#defs", o.definitions.join("\n")); +} + + +function onload() +{ + var optionTree = document.getElementById("option-tree"); + // gProgressBar = document.getElementById("progress-bar"); + // setProgress(0, 1); + + gNixOS = new NixOS(); + gOptionView = new OptionView(gNixOS.option, updatePanel); + optionTree.view = gOptionView; +} diff --git a/nixos/gui/chrome/content/myviewer.xul b/nixos/gui/chrome/content/myviewer.xul new file mode 100644 index 00000000000..2aeb9391d07 --- /dev/null +++ b/nixos/gui/chrome/content/myviewer.xul @@ -0,0 +1,63 @@ + + + + + + + + + + +