From f40362898a6885cbb39ed12a2fda2334347b2e24 Mon Sep 17 00:00:00 2001 From: Tobias Happ Date: Sun, 24 Nov 2019 00:37:40 +0100 Subject: [PATCH] Add modules --- modules/build/activation.nix | 112 ++++++++++++++++++ modules/build/config.nix | 45 +++++++ modules/build/initial-build/default.nix | 54 +++++++++ .../initial-build/nix-on-droid.nix.default | 39 ++++++ modules/default.nix | 39 ++++++ modules/environment/etc/default.nix | 108 +++++++++++++++++ modules/environment/etc/make-etc.sh | 41 +++++++ modules/environment/etc/setup-etc.sh | 85 +++++++++++++ modules/environment/files.nix | 36 ++++++ modules/environment/links.nix | 60 ++++++++++ modules/environment/login/default.nix | 55 +++++++++ modules/environment/login/login-inner.nix | 70 +++++++++++ modules/environment/login/login.nix | 23 ++++ modules/environment/path.nix | 67 +++++++++++ modules/home-manager.nix | 59 +++++++++ modules/lib-bash/activation-init.sh | 20 ++++ modules/lib-bash/color-echo.sh | 37 ++++++ modules/module-list.nix | 14 +++ modules/user.nix | 81 +++++++++++++ 19 files changed, 1045 insertions(+) create mode 100644 modules/build/activation.nix create mode 100644 modules/build/config.nix create mode 100644 modules/build/initial-build/default.nix create mode 100644 modules/build/initial-build/nix-on-droid.nix.default create mode 100644 modules/default.nix create mode 100644 modules/environment/etc/default.nix create mode 100644 modules/environment/etc/make-etc.sh create mode 100644 modules/environment/etc/setup-etc.sh create mode 100644 modules/environment/files.nix create mode 100644 modules/environment/links.nix create mode 100644 modules/environment/login/default.nix create mode 100644 modules/environment/login/login-inner.nix create mode 100644 modules/environment/login/login.nix create mode 100644 modules/environment/path.nix create mode 100644 modules/home-manager.nix create mode 100644 modules/lib-bash/activation-init.sh create mode 100644 modules/lib-bash/color-echo.sh create mode 100644 modules/module-list.nix create mode 100644 modules/user.nix diff --git a/modules/build/activation.nix b/modules/build/activation.nix new file mode 100644 index 0000000..3802883 --- /dev/null +++ b/modules/build/activation.nix @@ -0,0 +1,112 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.build; + + # Programs that always should be available on the activation + # script's PATH. + activationBinPaths = lib.makeBinPath [ + pkgs.bash + pkgs.coreutils + pkgs.findutils + pkgs.gnused + pkgs.ncurses # For `tput`. + pkgs.nix + ]; + + activationCmds = concatStringsSep "\n" ( + mapAttrsToList (name: value: '' + noteEcho "Activating ${name}" + ${value} + '') cfg.activation + ); + + activationScript = pkgs.writeScript "activation-script" '' + #!${pkgs.runtimeShell} + + set -eu + set -o pipefail + + cd $HOME + + export PATH="${activationBinPaths}" + + ${builtins.readFile ../lib-bash/color-echo.sh} + ${builtins.readFile ../lib-bash/activation-init.sh} + + ${activationCmds} + ''; +in + +{ + + ###### interface + + options = { + + build = { + activation = mkOption { + default = {}; + type = types.attrs; + description = '' + Activation scripts for the nix-on-droid environment. + + Any script should respect the DRY_RUN + variable, if it is set then no actual action should be taken. + The variable DRY_RUN_CMD is set to + echo if dry run is enabled. Thus, many cases you + can use the idiom $DRY_RUN_CMD rm -rf /. + ''; + }; + + activationPackage = mkOption { + type = types.package; + readOnly = true; + internal = true; + description = "Derivation with activation script."; + }; + + etc = mkOption { + type = types.package; + internal = true; + description = "Package containing /etc files."; + }; + }; + + }; + + + ###### implementation + + config = { + + build.activationPackage = + pkgs.runCommand + "nix-on-droid-generation" + { + preferLocalBuild = true; + allowSubstitutes = false; + } + '' + mkdir --parents $out/filesystem/{bin,usr/{bin,lib}} + + cp ${activationScript} $out/activate + + ln --symbolic ${config.build.etc}/etc $out/etc + ln --symbolic ${config.environment.path} $out/nix-on-droid-path + + ln --symbolic ${config.environment.files.login} $out/filesystem/bin/login + ln --symbolic ${config.environment.files.loginInner} $out/filesystem/usr/lib/login-inner + + ln --symbolic ${config.environment.binSh} $out/filesystem/bin/sh + ln --symbolic ${config.environment.usrBinEnv} $out/filesystem/usr/bin/env + ''; + + }; + +} diff --git a/modules/build/config.nix b/modules/build/config.nix new file mode 100644 index 0000000..c739cf1 --- /dev/null +++ b/modules/build/config.nix @@ -0,0 +1,45 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + + ###### interface + + options = { + + build = { + initialBuild = mkOption { + type = types.bool; + default = false; + internal = true; + description = '' + Whether this is the initial build for the bootstrap zip ball. + Should not be enabled manually, see + initial-build.nix. + ''; + }; + + installationDir = mkOption { + type = types.path; + internal = true; + readOnly = true; + description = "Path to installation directory."; + }; + }; + + }; + + + ###### implementation + + config = { + + build.installationDir = "/data/data/com.termux.nix/files/usr"; + + }; + +} diff --git a/modules/build/initial-build/default.nix b/modules/build/initial-build/default.nix new file mode 100644 index 0000000..bedcf53 --- /dev/null +++ b/modules/build/initial-build/default.nix @@ -0,0 +1,54 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + + ###### interface + + options = { + + build = { + arch = mkOption { + type = types.enum [ "aarch64" "i686" ]; + description = "Destination arch."; + }; + + channel = { + nixpkgs = mkOption { + type = types.str; + default = "https://nixos.org/channels/nixos-19.09"; + description = "Channel URL for nixpkgs."; + }; + + nix-on-droid = mkOption { + type = types.str; + default = "https://github.com/t184256/nix-on-droid-bootstrap/archive/master.tar.gz"; + description = "Channel URL for nix-on-droid."; + }; + }; + }; + + }; + + + ###### implementation + + config = { + + build.initialBuild = true; + + # /etc/group and /etc/passwd need to be build on target machine because + # uid and gid need to be determined. + environment.etc = { + "group".enable = false; + "nix-on-droid.nix.default".text = builtins.readFile ./nix-on-droid.nix.default; + "passwd".enable = false; + }; + + }; + +} diff --git a/modules/build/initial-build/nix-on-droid.nix.default b/modules/build/initial-build/nix-on-droid.nix.default new file mode 100644 index 0000000..c83e894 --- /dev/null +++ b/modules/build/initial-build/nix-on-droid.nix.default @@ -0,0 +1,39 @@ +{ pkgs, ... }: + +{ + # Simply install just the packages + environment.packages = with pkgs; [ + # User-facing stuff that you really really want to have + vim # or some other editor, e.g. nano or neovim + + # Some common stuff that people expect to have + #diffutils + #findutils + #utillinux + #tzdata + #hostname + #man + #less + #gnugrep + #gnupg + #gnused + #gnutar + #bzip2 + #gzip + #xz + #zip + #unzip + ]; + + # After installing home-manager channel like + # nix-channel --add https://github.com/rycee/home-manager/archive/master.tar.gz home-manager + # nix-channel --update + # you can configure home-manager in here like + #home-manager.config = + # { pkgs, ... }: + # { + # # insert home-manager config + # }; +} + +# vim: ft=nix diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..114aeaf --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,39 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ pkgs ? import { }, initialBuild ? false, config ? { } }: + +with pkgs.lib; + +let + homeDir = builtins.getEnv "HOME"; + configFile = homeDir + "/.config/nixpkgs/nix-on-droid.nix"; + + hasConfigFile = builtins.pathExists configFile; + + rawModule = evalModules { + modules = [ + { + _module.args = { inherit pkgs; }; + } + ] + ++ optional (!initialBuild && hasConfigFile) configFile + ++ optional (!initialBuild && !hasConfigFile && pkgs.config ? nix-on-droid) pkgs.config.nix-on-droid + ++ optional initialBuild config + ++ import ./module-list.nix; + }; + + failedAssertions = map (x: x.message) (filter (x: !x.assertion) rawModule.config.assertions); + + module = + if failedAssertions != [] + then throw "\nFailed assertions:\n${concatMapStringsSep "\n" (x: "- ${x}") failedAssertions}" + else showWarnings rawModule.config.warnings rawModule; +in + +if initialBuild +then module.config +else { + inherit (module.config.build) activationPackage; + inherit (module.config.environment) path; +} diff --git a/modules/environment/etc/default.nix b/modules/environment/etc/default.nix new file mode 100644 index 0000000..7e460a2 --- /dev/null +++ b/modules/environment/etc/default.nix @@ -0,0 +1,108 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +let + etc' = filter (f: f.enable) (attrValues config.environment.etc); + + etc = pkgs.stdenvNoCC.mkDerivation { + name = "etc"; + + builder = ./make-etc.sh; + + preferLocalBuild = true; + allowSubstitutes = false; + + sources = map (x: x.source) etc'; + targets = map (x: x.target) etc'; + }; + + fileType = types.submodule ( + { name, config, ... }: + { + options = { + + enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether this /etc file should be generated. This + option allows specific /etc files to be disabled. + ''; + }; + + target = mkOption { + type = types.str; + description = '' + Name of symlink (relative to /etc). + Defaults to the attribute name. + ''; + }; + + text = mkOption { + type = types.nullOr types.lines; + default = null; + description = "Text of the file."; + }; + + source = mkOption { + type = types.path; + description = "Path of the source file."; + }; + + }; + + config = { + target = mkDefault name; + source = mkIf (config.text != null) ( + let name' = "etc-" + baseNameOf name; + in mkDefault (pkgs.writeText name' config.text)); + }; + + } + ); +in + +{ + + ###### interface + + options = { + + environment.etc = mkOption { + type = types.loaOf fileType; + default = {}; + example = literalExample '' + { + example-configuration-file = { + source = "/nix/store/.../etc/dir/file.conf.example"; + }; + "default/useradd".text = "GROUP=100 ..."; + } + ''; + description = '' + Set of files that have to be linked in /etc. + ''; + }; + + }; + + + ###### implementation + + config = { + + build = { + inherit etc; + + activation.setUpEtc = '' + $DRY_RUN_CMD bash ${./setup-etc.sh} /etc ${etc}/etc + ''; + }; + + }; + +} diff --git a/modules/environment/etc/make-etc.sh b/modules/environment/etc/make-etc.sh new file mode 100644 index 0000000..e8e561d --- /dev/null +++ b/modules/environment/etc/make-etc.sh @@ -0,0 +1,41 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +# inspired by https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/make-etc.sh + +source $stdenv/setup + +mkdir -p $out + +set -f +sources_=($sources) +targets_=($targets) +set +f + +for ((i = 0; i < ${#targets_[@]}; i++)); do + source="${sources_[$i]}" + target="${targets_[$i]}" + + if [[ "$source" =~ '*' ]]; then + + # If the source name contains '*', perform globbing. + mkdir -p $out/etc/$target + for fn in $source; do + ln -s "$fn" $out/etc/$target/ + done + + else + + mkdir -p $out/etc/$(dirname $target) + if ! [ -e $out/etc/$target ]; then + ln -s $source $out/etc/$target + else + echo "duplicate entry $target -> $source" + if test "$(readlink $out/etc/$target)" != "$source"; then + echo "mismatched duplicate entry $(readlink $out/etc/$target) <-> $source" + exit 1 + fi + fi + + fi +done diff --git a/modules/environment/etc/setup-etc.sh b/modules/environment/etc/setup-etc.sh new file mode 100644 index 0000000..c9cfa7c --- /dev/null +++ b/modules/environment/etc/setup-etc.sh @@ -0,0 +1,85 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +# inspired by https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/setup-etc.pl + +etc="${1}" +static="/etc/static" +new_etc="${2}" + +function atomic_symlink() { + local source="${1}" + local target="${2}" + local target_tmp="${target}.tmp" + + mkdir -p "$(dirname "${target_tmp}")" + ln -sf "${source}" "${target_tmp}" + mv -T "${target_tmp}" "${target}" +} + +# Remove dangling symlinks that point to /etc/static. These are +# configuration files that existed in a previous configuration but not +# in the current one. +function cleanup() { + local file + for file in $(find "${etc}" -xtype l); do + local target="$(readlink "${file}")" + if [[ ! -L "${target}" ]]; then + echo "removing obsolete symlink '${file}'..." + rm "${file}" + fi + done +} + +# Returns 0 if the argument points to the files in /etc/static. That +# means either argument is a symlink to a file in /etc/static or a +# directory with all children being static. +function is_static() { + local path="${1}" + + if [[ -L "${path}" ]]; then + [[ "$(readlink "${path}")" == ${static}/* ]] + return + fi + + if [[ -d "${path}" ]]; then + local file + for file in "${path}"/*; do + is_static "${file}" || return + done + fi + + false +} + +function link() { + if [[ ! -d "${new_etc}" ]]; then + return + fi + + local name + for name in $(find "${new_etc}/" -type l | sed -e "s,^${new_etc}/,,"); do + local target="${etc}/${name}" + + mkdir -p "$(dirname "${target}")" + + if [[ -e "${target}" ]] && ! is_static "${target}"; then + echo "Linking of ${target} failed. Please remove this file." + else + atomic_symlink "${static}/${name}" "${target}" + fi + done +} + +# On initial build /etc/static is a directory instead of a symlink +if [[ -d "${etc}/static" ]]; then + rm --recursive "${etc}/static" +fi + +# Atomically update /etc/static to point at the etc files of the +# current configuration. +atomic_symlink "${new_etc}" "${etc}/static" + +cleanup + +link diff --git a/modules/environment/files.nix b/modules/environment/files.nix new file mode 100644 index 0000000..04d118c --- /dev/null +++ b/modules/environment/files.nix @@ -0,0 +1,36 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + + ###### interface + + options = { + + }; + + + ###### implementation + + config = { + + environment.etc = { + "nix/nix.conf".text = '' + sandbox = false + substituters = https://cache.nixos.org https://nix-on-droid.cachix.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= nix-on-droid.cachix.org-1:56snoMJTXmDRC1Ei24CmKoUqvHJ9XCp+nidK7qkMQrU= + ''; + + "resolv.conf".text = '' + nameserver 1.1.1.1 + nameserver 8.8.8.8 + ''; + }; + + }; + +} diff --git a/modules/environment/links.nix b/modules/environment/links.nix new file mode 100644 index 0000000..5475b62 --- /dev/null +++ b/modules/environment/links.nix @@ -0,0 +1,60 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.environment; +in + +{ + + ###### interface + + options = { + + environment = { + binSh = mkOption { + type = types.str; + readOnly = true; + description = "Path to /bin/sh executable."; + }; + + usrBinEnv = mkOption { + type = types.str; + readOnly = true; + description = "Path to /usr/bin/env executable."; + }; + }; + + }; + + + ###### implementation + + config = { + + build.activation = { + linkBinSh = '' + $DRY_RUN_CMD mkdir $VERBOSE_ARG --parents /bin + $DRY_RUN_CMD ln $VERBOSE_ARG --symbolic --force ${cfg.binSh} /bin/.sh.tmp + $DRY_RUN_CMD mv $VERBOSE_ARG /bin/.sh.tmp /bin/sh + ''; + + linkUsrBinEnv = '' + $DRY_RUN_CMD mkdir $VERBOSE_ARG --parents /usr/bin + $DRY_RUN_CMD ln $VERBOSE_ARG --symbolic --force ${cfg.usrBinEnv} /usr/bin/.env.tmp + $DRY_RUN_CMD mv $VERBOSE_ARG /usr/bin/.env.tmp /usr/bin/env + ''; + }; + + environment = { + binSh = "${pkgs.bashInteractive}/bin/sh"; + usrBinEnv = "${pkgs.coreutils}/bin/env"; + }; + + }; + +} diff --git a/modules/environment/login/default.nix b/modules/environment/login/default.nix new file mode 100644 index 0000000..8ce4d2e --- /dev/null +++ b/modules/environment/login/default.nix @@ -0,0 +1,55 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, customPkgs, ... }: + +with lib; + +let + login = pkgs.callPackage ./login.nix { inherit config; }; + + loginInner = pkgs.callPackage ./login-inner.nix { inherit config customPkgs; }; +in + +{ + + ###### interface + + options = { + + environment.files = { + + login = mkOption { + type = types.package; + readOnly = true; + description = "Login script."; + }; + + loginInner = mkOption { + type = types.package; + readOnly = true; + description = "Login-inner script."; + }; + + }; + + }; + + + ###### implementation + + config = { + + build.activation.installLoginScripts = '' + $DRY_RUN_CMD mkdir $VERBOSE_ARG --parents /bin /usr/lib + $DRY_RUN_CMD cp $VERBOSE_ARG ${login} /bin/login + $DRY_RUN_CMD cp $VERBOSE_ARG ${loginInner} /usr/lib/login-inner + ''; + + environment.files = { + inherit login loginInner; + }; + + }; + +} diff --git a/modules/environment/login/login-inner.nix b/modules/environment/login/login-inner.nix new file mode 100644 index 0000000..f1af4c1 --- /dev/null +++ b/modules/environment/login/login-inner.nix @@ -0,0 +1,70 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, customPkgs, writeText }: + +let + inherit (customPkgs.packageInfo) cacert coreutils nix; +in + +writeText "login-inner" '' + set -e + + [ "$#" -gt 0 ] || echo "Welcome to Nix-on-Droid!" + + [ "$#" -gt 0 ] || echo "If nothing works, use the rescue shell and read ${config.build.installationDir}/usr/lib/login-inner" + [ "$#" -gt 0 ] || echo "If it does not help, report bugs at https://github.com/t184256/nix-on-droid-bootstrap/issues" + + export USER="${config.user.userName}" + export HOME="${config.user.home}" + + ${lib.optionalString config.build.initialBuild '' + [ "$#" -gt 0 ] || echo "Sourcing Nix environment..." + . ${nix}/etc/profile.d/nix.sh + + export NIX_SSL_CERT_FILE=${cacert} + + echo "Installing and updating nix-channels..." + ${nix}/bin/nix-channel --add ${config.build.channel.nixpkgs} nixpkgs + ${nix}/bin/nix-channel --update nixpkgs + ${nix}/bin/nix-channel --add ${config.build.channel.nix-on-droid} nix-on-droid + ${nix}/bin/nix-channel --update nix-on-droid + + echo "Copy default nix-on-droid config..." + ${coreutils}/bin/mkdir --parents $HOME/.config/nixpkgs + ${coreutils}/bin/cp /etc/nix-on-droid.nix.default $HOME/.config/nixpkgs/nix-on-droid.nix + + echo "Installing first nix-on-droid generation..." + ${nix}/bin/nix build --no-link --file "" nix-on-droid + $(${nix}/bin/nix path-info --file "" nix-on-droid)/bin/nix-on-droid switch + + echo + echo "Congratulations! Now you have Nix installed with some default packages like bashInteractive, \ + coreutils, cacert and most important nix-on-droid itself to manage local configuration, see" + echo " nix-on-droid help" + echo "or in the config file" + echo " ~/.config/nixpkgs/nix-on-droid.nix" + echo + echo "You can go for the bare nix-on-droid setup or you can configure your phone via home-manager. See \ + config file for further information." + echo + ''} + + [ "$#" -gt 0 ] || echo "Sourcing Nix environment..." + . $HOME/.nix-profile/etc/profile.d/nix.sh + + if [ -e "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" ]; then + [ "$#" -gt 0 ] || echo "Sourcing home-manager environment..." + export NIX_PATH=$HOME/.nix-defexpr/channels''${NIX_PATH:+:}$NIX_PATH + . "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" + fi + + # Workaround for https://github.com/NixOS/nix/issues/1865 + export NIX_PATH=nixpkgs=$HOME/.nix-defexpr/channels/nixpkgs/:$NIX_PATH + + if [ "$#" -eq 0 ]; then + exec /usr/bin/env bash + else + exec /usr/bin/env "$@" + fi +'' diff --git a/modules/environment/login/login.nix b/modules/environment/login/login.nix new file mode 100644 index 0000000..17c502f --- /dev/null +++ b/modules/environment/login/login.nix @@ -0,0 +1,23 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, writeScript }: + +writeScript "login" '' + #!/system/bin/sh + set -e + + export USER="${config.user.userName}" + export PROOT_TMP_DIR=${config.build.installationDir}/tmp + export PROOT_L2S_DIR=${config.build.installationDir}/.l2s + + exec "${config.build.installationDir}/bin/proot-static" \ + -b ${config.build.installationDir}/nix:/nix \ + -b ${config.build.installationDir}/bin:/bin \ + -b ${config.build.installationDir}/etc:/etc \ + -b ${config.build.installationDir}/tmp:/tmp \ + -b ${config.build.installationDir}/usr:/usr \ + -b /:/android \ + --link2symlink \ + ${config.build.installationDir}/bin/sh ${config.build.installationDir}/usr/lib/login-inner "$@" +'' diff --git a/modules/environment/path.nix b/modules/environment/path.nix new file mode 100644 index 0000000..832c5b1 --- /dev/null +++ b/modules/environment/path.nix @@ -0,0 +1,67 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.environment; +in + +{ + + ###### interface + + options = { + + environment = { + packages = mkOption { + type = types.listOf types.package; + default = []; + description = "List of packages to be installed as user packages."; + }; + + path = mkOption { + type = types.package; + readOnly = true; + internal = true; + description = "Derivation for installing user packages."; + }; + }; + + }; + + + ###### implementation + + config = { + + build.activation.installPackages = '' + $DRY_RUN_CMD nix-env --install ${cfg.path} + ''; + + environment = { + packages = [ + (pkgs.callPackage ../../nix-on-droid { }) + pkgs.bashInteractive + pkgs.cacert + pkgs.coreutils + pkgs.less # since nix tools really want a pager available, #27 + pkgs.nix + ]; + + path = pkgs.buildEnv { + name = "nix-on-droid-path"; + + paths = cfg.packages; + + meta = { + description = "Environment of packages installed through nix-on-droid."; + }; + }; + }; + + }; + +} diff --git a/modules/home-manager.nix b/modules/home-manager.nix new file mode 100644 index 0000000..a4115d2 --- /dev/null +++ b/modules/home-manager.nix @@ -0,0 +1,59 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.home-manager; + + hmModule = types.submodule ({ name, ... }: { + imports = import { inherit lib pkgs; }; + + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + home.username = config.user.userName; + home.homeDirectory = config.user.home; + }; + }); +in + +{ + + ###### interface + + options = { + + home-manager = { + config = mkOption { + type = types.nullOr hmModule; + default = null; + description = "Home Manager configuration."; + }; + + useUserPackages = mkEnableOption '' + installation of user packages through the + option. + ''; + }; + + }; + + + ###### implementation + + config = mkIf (cfg.config != null) { + + inherit (config) assertions warnings; + + build.activation.homeManager = '' + ${cfg.config.home.activationPackage}/activate + ''; + + environment.packages = mkIf cfg.useUserPackages cfg.config.home.packages; + + }; +} diff --git a/modules/lib-bash/activation-init.sh b/modules/lib-bash/activation-init.sh new file mode 100644 index 0000000..7ad12c2 --- /dev/null +++ b/modules/lib-bash/activation-init.sh @@ -0,0 +1,20 @@ +if [[ -v VERBOSE ]]; then + export VERBOSE_ECHO=echo + export VERBOSE_ARG="--verbose" +else + export VERBOSE_ECHO=true + export VERBOSE_ARG="" +fi + +if [[ -v DRY_RUN ]] ; then + echo "This is a dry run" + export DRY_RUN_CMD=echo +else + $VERBOSE_ECHO "This is a live run" + export DRY_RUN_CMD="" +fi + +if [[ -v VERBOSE ]]; then + echo -n "Using Nix version: " + nix --version +fi diff --git a/modules/lib-bash/color-echo.sh b/modules/lib-bash/color-echo.sh new file mode 100644 index 0000000..ef708b2 --- /dev/null +++ b/modules/lib-bash/color-echo.sh @@ -0,0 +1,37 @@ +# The check for terminal output and color support is heavily inspired +# by https://unix.stackexchange.com/a/10065. + +function setupColors() { + normalColor="" + errorColor="" + warnColor="" + noteColor="" + + # Check if stdout is a terminal. + if [[ -t 1 ]]; then + # See if it supports colors. + local ncolors + ncolors=$(tput colors) + + if [[ -n "$ncolors" && "$ncolors" -ge 8 ]]; then + normalColor="$(tput sgr0)" + errorColor="$(tput bold)$(tput setaf 1)" + warnColor="$(tput setaf 3)" + noteColor="$(tput bold)$(tput setaf 6)" + fi + fi +} + +setupColors + +function errorEcho() { + echo "${errorColor}$*${normalColor}" +} + +function warnEcho() { + echo "${warnColor}$*${normalColor}" +} + +function noteEcho() { + echo "${noteColor}$*${normalColor}" +} diff --git a/modules/module-list.nix b/modules/module-list.nix new file mode 100644 index 0000000..8c10928 --- /dev/null +++ b/modules/module-list.nix @@ -0,0 +1,14 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +[ + ./build/activation.nix + ./build/config.nix + ./environment/etc + ./environment/files.nix + ./environment/login + ./environment/links.nix + ./environment/path.nix + ./user.nix + +] diff --git a/modules/user.nix b/modules/user.nix new file mode 100644 index 0000000..80b7942 --- /dev/null +++ b/modules/user.nix @@ -0,0 +1,81 @@ +# Licensed under GNU Lesser General Public License v3 or later, see COPYING. +# Copyright (c) 2019 Alexander Sosedkin and other contributors, see AUTHORS. + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.user; + + idsDerivation = pkgs.runCommand "ids.nix" {} '' + cat > $out <