├── .dir-locals.el ├── .envrc ├── .gitignore ├── .reuse ├── dep5 └── templates │ └── mpl-2-0.jinja2 ├── LICENSES ├── CC-BY-SA-4.0.txt ├── CC0-1.0.txt └── MPL-2.0.txt ├── README.md ├── README.md.license ├── doc ├── README.org ├── reuse.org ├── structure.org ├── style_and_vocabulary.org └── writing_documentation.org ├── examples ├── apache │ └── default.nix ├── certbot │ └── default.nix ├── crond │ └── default.nix ├── default.nix ├── gitea │ └── default.nix ├── home-assistant │ └── default.nix ├── hydra │ └── default.nix ├── jmusicbot │ └── default.nix ├── minecraft │ └── default.nix ├── nginx │ └── default.nix ├── nix │ └── default.nix ├── pantalaimon │ └── default.nix ├── php-fpm │ ├── default.nix │ └── documentRoot │ │ └── index.php └── postfix │ ├── default.nix │ └── test-mail.sh ├── flake.lock ├── flake.lock.license ├── flake.nix ├── lib ├── dag.nix ├── generators.nix └── make-system.nix ├── modules ├── assertions.nix ├── bootloader │ └── default.nix ├── dumb-init │ └── default.nix ├── environment.nix ├── ids.nix ├── init.nix ├── initrd │ ├── default.nix │ └── init.sh ├── misc │ └── iana.nix ├── nix.nix ├── runit │ ├── default.nix │ ├── finish.nix │ ├── log.nix │ ├── run.nix │ ├── stage-1.sh │ ├── stage-2.sh │ └── stage-3.sh ├── security │ └── ca.nix ├── services │ ├── apache2-nixos.nix │ ├── certbot.nix │ ├── crond.nix │ ├── dovecot.nix │ ├── getty.nix │ ├── gitea.nix │ ├── home-assistant.nix │ ├── hydra.nix │ ├── jmusicbot.nix │ ├── minecraft.nix │ ├── mosquitto.nix │ ├── mysql.nix │ ├── nginx.nix │ ├── pantalaimon.nix │ ├── php-fpm.nix │ ├── postfix.nix │ ├── postgresql.nix │ ├── socklog.nix │ └── zigbee2mqtt.nix ├── system.nix └── users.nix ├── nix-ng.png ├── nix-ng.png.license └── overlay ├── cronie.nix ├── default.nix ├── run-vm-linux.nix ├── sigell ├── .gitignore ├── CHANGELOG.md ├── app │ ├── CmdLine.hs │ ├── Config.hs │ └── Main.hs ├── cabal.nix ├── examples │ ├── 1.json │ └── 2.json ├── hie.yaml └── sigell.cabal ├── tiny-linux.nix └── trivial-builders.nix /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ; SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | ; 3 | ; SPDX-License-Identifier: MPL-2.0 4 | ; 5 | ; This Source Code Form is subject to the terms of the Mozilla Public 6 | ; License, v. 2.0. If a copy of the MPL was not distributed with this 7 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | ((nil . ((fill-column . 80)))) 10 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | use flake 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: CC0-1.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | /result* 10 | .direnv 11 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: NixNG 3 | Upstream-Contact: Richard Brežák <> 4 | Source: https://github.com/MagicRB/NixNG 5 | 6 | # Sample paragraph, commented out: 7 | # 8 | # Files: src/* 9 | # Copyright: $YEAR $NAME <$CONTACT> 10 | # License: ... 11 | -------------------------------------------------------------------------------- /.reuse/templates/mpl-2-0.jinja2: -------------------------------------------------------------------------------- 1 | {% for copyright_line in copyright_lines %} 2 | {{ copyright_line }} 3 | {% endfor %} 4 | 5 | {% for expression in spdx_expressions %} 6 | SPDX-License-Identifier: {{ expression }} 7 | {% endfor %} 8 | 9 | This Source Code Form is subject to the terms of the Mozilla Public 10 | License, v. 2.0. If a copy of the MPL was not distributed with this 11 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 12 | -------------------------------------------------------------------------------- /LICENSES/CC0-1.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This project has moved. 2 | 3 | NixNG has a new home at [nix-community/NixNG](https://github.com/nix-community/NixNG). 4 | -------------------------------------------------------------------------------- /README.md.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | SPDX-License-Identifier: CC-BY-SA-4.0 -------------------------------------------------------------------------------- /doc/README.org: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | # SPDX-License-Identifier: MPL-2.0 4 | 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | * NixNG Documentation 10 | 11 | Welcome to the documentation of the NixNG project! 12 | 13 | This documentation is intended for NixNG developers, NixNG module documentation, 14 | which will be autogenerated like the one on [[https://search.nixos.org/]] is 15 | planned. 16 | 17 | First things first, you can get an overview of the repository structure 18 | [[file:structure.org][here]]. Then please make sure to familiarize yourself with [[file:reuse.org][REUSE]]. To learn how to 19 | contribute to this documentation visit [[file:writing_documentation.org][Writing Documentation]]. There are also 20 | some [[file:style_and_vocabulary.org][generic hints]] on the style of the whole project. 21 | -------------------------------------------------------------------------------- /doc/reuse.org: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | # SPDX-License-Identifier: MPL-2.0 4 | 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | * REUSE 10 | 11 | NixNG utilizes [[https://github.com/fsfe/reuse-tool][~reuse-tool~]] to specify the licenses for all files in the 12 | project. We utilize several licenses, described below each in it's own section. 13 | When creating new files please utilize the commands below to add a proper 14 | license header to all files. \\ 15 | \\ 16 | To check for REUSE compliance run: 17 | #+BEGIN_SRC shell-script 18 | reuse link 19 | #+END_SRC 20 | 21 | ** CC-BY-SA 22 | This license is used for all documentation and related documents. 23 | 24 | - SPDX: [[https://spdx.org/licenses/CC-BY-SA-4.0.html][CC-BY-SA-4.0]] 25 | 26 | *** Command 27 | 28 | #+BEGIN_SRC shell-script :noweb yes 29 | reuse addheader --copyright "Richard Brežák and NixNG contributors" --license CC-BY-SA-4.0 30 | #+END_SRC 31 | 32 | ** MPL-2.0 33 | This license is used for all files containing primarly code. 34 | 35 | - SPDX: [[https://spdx.org/licenses/MPL-2.0.html][MPL-2.0]] 36 | 37 | *** Command 38 | 39 | #+BEGIN_SRC shell-script 40 | reuse addheader --copyright "Richard Brežák and NixNG contributors" --license MPL-2.0 --template mpl-2-0 41 | #+END_SRC 42 | 43 | ** CC0 44 | This license is used for minor files and machine generated files such as: 45 | =flake.lock=, =.gitignore=. 46 | 47 | - SPDX: [[https://spdx.org/licenses/CC0-1.0.html][CC0-1.0]] 48 | 49 | *** Command 50 | 51 | #+BEGIN_SRC shell-script 52 | reuse addheader --copyright "Richard Brežák and NixNG contributors" --license CC0 53 | #+END_SRC 54 | -------------------------------------------------------------------------------- /doc/structure.org: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | # SPDX-License-Identifier: MPL-2.0 4 | 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | * Repository Structure 10 | 11 | This repository is split into 4 main parts, each of them has a clearly defined 12 | purpose, more may be and will be added later. 13 | 14 | ** ~/overlay~ 15 | This directory only contains new packages, introduced by NixNG. These packages 16 | are developed with NixNG or specifically needed to make NixNG work. Examples 17 | include: ~sigell~ - our signal dispatching binary. 18 | 19 | ** ~/doc~ 20 | This is the directory you're currently in. It contains all of manually written 21 | NixNG documentation. Please visit [[file:writing_documentation.org][Writing Documentation]] to learn how to 22 | contribute to this doc. 23 | 24 | ** ~/modules~ 25 | This directory contains all the NixOS modules making NixNG possible. They're 26 | structured into directories, which make sense somewhat, a proper structuring 27 | guide hasn't yet been made. 28 | 29 | ** ~/lib~ 30 | This directory contains the NixNG Nix library, it's the the ~nixpkgs.lib~ 31 | attribute set we're all familiar with. The one rule that it shares with its 32 | nixpgks counterpart is that it must be system independent. System dependent 33 | stuff should go into ~/overlay~. 34 | 35 | ** ~/examples~ 36 | This directory holds examples utilising NixNG to build container images. This 37 | closesly relates to a test framework and is one of the areas that needs 38 | work. You can find an issue related to this on the issue tracker. 39 | -------------------------------------------------------------------------------- /doc/style_and_vocabulary.org: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | # SPDX-License-Identifier: MPL-2.0 4 | 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | * Style and Vocabulary 10 | ** Style 11 | *** 80 Columns 12 | Stick to 80 columns in these documents. Org mode has 13 | visual line wrapping (~visual-line-mode~ in Emacs), but we cannot assume 14 | everyone has access to Emacs. 15 | *** Nix Library Imports 16 | It's preferred to just ~with lib;~ and ~with nglib;~ when either is needed, the 17 | function names are well known and not ambigous so they can't be mistaken with 18 | packages or other such things. 19 | 20 | ** Vocabulary 21 | These are basic term definitions, mostly common variable names which help in 22 | writing understandable and uniform code. 23 | 24 | - *nixpkgs* - a "raw" nixpkgs attribute set, as from a flake input, requires 25 | importing with ~system~, generally refers to the stable branch of nixpkgs 26 | - *nixpkgs-unstable/master* - a more specific version of nixpkgs 27 | - *pkgs* - already imported nixpkgs, specific to a system 28 | - *lib* - the Nix library from nixpkgs 29 | - *nglib* - NixNG's own Nix library 30 | - *NixOS module* - TBD 31 | - *NixNG module* - a module specific to NixNG 32 | - *home-manager module* - a module specific to home-manager 33 | -------------------------------------------------------------------------------- /doc/writing_documentation.org: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | # SPDX-License-Identifier: MPL-2.0 4 | 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | * Writing Documentation 10 | 11 | This documentation uses a format called [[https://orgmode.org/][Org]]. It's native to Emacs but the subset 12 | of it that is used here is small enough and simple enoug that it can be written 13 | in any text editor. To familiarize yourself with Org, take a look at this [[https://nhigham.com/2017/11/02/org-mode-syntax-cheat-sheet/][Org 14 | Mode Syntax Cheat Sheet]]. 15 | 16 | ** Editor Support 17 | *** GNU Emacs 18 | Org is native to Emacs, so if you have Emacs, you already have Org setup and 19 | ready. 20 | *** Vim/NVim 21 | Vim/NVim doesn't have full support for all of Orgs features, but the subset used 22 | here is supported. You can get support by installing [[https://github.com/axvr/org.vim][org.vim]]. 23 | *** VSCode/VSCodium 24 | VSCode/VSCodium doesn't have full support for all of Orgs features, but the 25 | subset used here is supported. You can get support by installing 26 | [[https://marketplace.visualstudio.com/items?itemName=vscode-org-mode.org-mode][vscode-org-mode.org-mode]]. 27 | -------------------------------------------------------------------------------- /examples/apache/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-apache"; 14 | config = ({ pkgs, config, ... }: 15 | let 16 | ids = config.ids; 17 | in 18 | { 19 | config = { 20 | dumb-init = { 21 | enable = true; 22 | type.services = { }; 23 | }; 24 | init.services.apache2 = { 25 | shutdownOnExit = true; 26 | ensureSomething.link."documentRoot" = { 27 | src = "${pkgs.apacheHttpd}/htdocs"; 28 | dst = "/var/www"; 29 | }; 30 | }; 31 | services.apache2 = { 32 | enable = true; 33 | envsubst = true; 34 | configuration = [ 35 | { 36 | LoadModule = [ 37 | [ "mpm_event_module" "modules/mod_mpm_event.so" ] 38 | [ "log_config_module" "modules/mod_log_config.so" ] 39 | [ "unixd_module" "modules/mod_unixd.so" ] 40 | [ "authz_core_module" "modules/mod_authz_core.so" ] 41 | [ "dir_module" "modules/mod_dir.so" ] 42 | [ "mime_module" "modules/mod_mime.so" ] 43 | ]; 44 | } 45 | { 46 | Listen = "0.0.0.0:80"; 47 | 48 | ServerRoot = "/var/www"; 49 | ServerName = "blowhole"; 50 | PidFile = "/httpd.pid"; 51 | 52 | DocumentRoot = "/var/www"; 53 | 54 | User = "www-data"; 55 | Group = "www-data"; 56 | } 57 | 58 | { 59 | ErrorLog = "/dev/stderr"; 60 | TransferLog = "/dev/stdout"; 61 | 62 | LogLevel = "info"; 63 | } 64 | 65 | { 66 | AddType = [ 67 | [ "image/svg+xml" "svg" "svgz" ] 68 | ]; 69 | AddEncoding = [ "gzip" "svgz" ]; 70 | 71 | TypesConfig = "${pkgs.apacheHttpd}/conf/mime.types"; 72 | } 73 | 74 | { 75 | Directory = { 76 | "/" = { 77 | Require = [ "all" "denied" ]; 78 | Options = "SymlinksIfOwnerMatch"; 79 | }; 80 | }; 81 | 82 | VirtualHost = { 83 | "*:80" = { 84 | Directory = { 85 | "/var/www" = { 86 | Require = [ "all" "granted" ]; 87 | Options = [ "-Indexes" "+FollowSymlinks" ]; 88 | DirectoryIndex = "\${DIRECTORY_INDEX:-index.html}"; 89 | }; 90 | }; 91 | }; 92 | }; 93 | } 94 | ]; 95 | }; 96 | }; 97 | }); 98 | } 99 | -------------------------------------------------------------------------------- /examples/certbot/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-certbot"; 14 | config = ({ pkgs, config, ... }: 15 | { 16 | config = { 17 | dumb-init = { 18 | enable = true; 19 | type.services = { }; 20 | }; 21 | 22 | services.certbot = { 23 | enable = true; 24 | 25 | acceptTerms = true; 26 | 27 | domains = { 28 | "redalder.org" = { 29 | extraDomains = [ 30 | "hydra.redalder.org" 31 | ]; 32 | webroot = "/var/www/acme"; 33 | email = "admin@redalder.org"; 34 | }; 35 | }; 36 | }; 37 | }; 38 | } 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /examples/crond/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-crond"; 14 | config = ({ pkgs, config, ... }: 15 | { 16 | config = { 17 | dumb-init = { 18 | enable = true; 19 | type.services = { }; 20 | }; 21 | services.crond = { 22 | enable = true; 23 | crontabs = { 24 | hydra = { 25 | environment = { 26 | PATH = "${pkgs.busybox}/bin"; 27 | }; 28 | jobs = [ 29 | ''*/2 * * * * root echo "asd"'' 30 | ]; 31 | }; 32 | }; 33 | }; 34 | }; 35 | } 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /examples/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | let 11 | examples = 12 | { "gitea" = ./gitea; 13 | "apache" = ./apache; 14 | "nginx" = ./nginx; 15 | "crond" = ./crond; 16 | "nix" = ./nix; 17 | "hydra" = ./hydra; 18 | "certbot" = ./certbot; 19 | "postfix" = ./postfix; 20 | "pantalaimon" = ./pantalaimon; 21 | "jmusicbot" = ./jmusicbot; 22 | "php-fpm" = ./php-fpm; 23 | "minecraft" = ./minecraft; 24 | "home-assistant" = ./home-assistant; 25 | }; 26 | in 27 | nixpkgs.lib.mapAttrs (_: v: import v { nglib = nglib nixpkgs.lib; inherit nixpkgs; }) examples 28 | -------------------------------------------------------------------------------- /examples/gitea/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-gitea"; 14 | config = ({ pkgs, ... }: 15 | { 16 | dumb-init = { 17 | enable = true; 18 | type.services = { }; 19 | }; 20 | init.services.gitea.shutdownOnExit = true; 21 | services.gitea = { 22 | enable = true; 23 | 24 | appName = "Gitea"; 25 | runMode = "prod"; 26 | user = "gitea"; 27 | 28 | secrets = { 29 | secretKeyFile = "/secret_key"; 30 | internalTokenFile = "/internal_token"; 31 | jwtSecretFile = "/jwt_secret"; 32 | lfsJwtSecretFile = "/lfs_jwt_secret"; 33 | }; 34 | 35 | configuration = { 36 | repository = { 37 | ROOT = "/data/gitea/git/repositories"; 38 | }; 39 | 40 | "repository.local" = { 41 | LOCAL_COPY_PATH = "/data/gitea/tmp/local-repo"; 42 | }; 43 | 44 | "repository.upload" = { 45 | TEMP_PATH = "/data/gitea/gitea/uploads"; 46 | }; 47 | 48 | server = { 49 | APP_DATA_PATH = "/data/gitea"; 50 | SSH_DOMAIN = "localhost"; 51 | HTTP_PORT = 3000; 52 | ROOT_URL = http://localhost:3000/; 53 | DISABLE_SSH = false; 54 | SSH_PORT = 22; 55 | SSH_LISTEN_PORT = 22; 56 | LFS_START_SERVER = true; 57 | LFS_CONTENT_PATH = "/data/gitea/git/lfs"; 58 | DOMAIN = "localhost"; 59 | LFS_JWT_SECRET = "#lfsJwtSecret#"; 60 | OFFLINE_MODE = false; 61 | }; 62 | 63 | database = { 64 | PATH = "/data/gitea/db.sqlite"; 65 | DB_TYPE = "sqlite3"; 66 | CHARSET = "utf8"; 67 | }; 68 | 69 | indexer = { 70 | ISSUE_INDEXER_PATH = "/data/gitea/gitea/indexers/issues.bleve"; 71 | REPO_INDEXER_PATH = "/data/gitea/gitea/indexers/repos.bleve"; 72 | }; 73 | session = { 74 | PROVIDER_CONFIG = "/data/gitea/gitea/sessions"; 75 | PROVIDER = "file"; 76 | }; 77 | 78 | picture = { 79 | AVATAR_UPLOAD_PATH = "/data/gitea/gitea/avatars"; 80 | REPOSITORY_AVATAR_UPLOAD_PATH = "/data/gitea/gitea/repo-avatars"; 81 | DISABLE_GRAVATAR = false; 82 | ENABLE_FEDERATED_AVATAR = true; 83 | }; 84 | 85 | attachment = { 86 | PATH = "/data/gitea/gitea/attachments"; 87 | }; 88 | 89 | security = { 90 | INSTALL_LOCK = true; 91 | SECRET_KEY = "#secretKey"; 92 | INTERNAL_TOKEN = "#internalToken#"; 93 | }; 94 | 95 | service = { 96 | DISABLE_REGISTRATION = false; 97 | REQUIRE_SIGNIN_VIEW = false; 98 | REGISTER_EMAIL_CONFIRM = false; 99 | ENABLE_NOTIFY_MAIL = false; 100 | ALLOW_ONLY_EXTERNAL_REGISTRATION = false; 101 | ENABLE_CAPTCHA = false; 102 | DEFAULT_KEEP_EMAIL_PRIVATE = false; 103 | DEFAULT_ALLOW_CREATE_ORGANIZATION = true; 104 | DEFAULT_ENABLE_TIMETRACKING = true; 105 | NO_REPLY_ADDRESS = "noreply.localhost"; 106 | }; 107 | 108 | oauth2.JWT_SECRET = "#jwtSecret#"; 109 | 110 | mailer.ENABLED = false; 111 | 112 | openid = { 113 | ENABLE_OPENID_SIGNIN = true; 114 | ENABLE_OPENID_SIGNUP = true; 115 | }; 116 | 117 | log = { 118 | MODE = "console"; 119 | LEVEL = "Debug"; 120 | }; 121 | }; 122 | }; 123 | } 124 | ); 125 | } 126 | -------------------------------------------------------------------------------- /examples/home-assistant/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-home-assistant"; 14 | config = ({ pkgs, config, lib, ... }: 15 | { 16 | config = { 17 | dumb-init = { 18 | enable = true; 19 | type.services = { }; 20 | }; 21 | 22 | init.services.home-assistant = { 23 | shutdownOnExit = true; 24 | }; 25 | init.services.zigbee2mqtt = { 26 | shutdownOnExit = false; 27 | }; 28 | 29 | services.mosquitto = { 30 | enable = true; 31 | config = {}; 32 | envsubst = true; 33 | }; 34 | 35 | services.zigbee2mqtt = { 36 | enable = true; 37 | envsubst = true; 38 | package = (import (pkgs.fetchFromGitHub { 39 | owner = "NixOS"; 40 | repo = "nixpkgs"; 41 | rev = "0c408a087b4751c887e463e3848512c12017be25"; 42 | sha256 = "sha256-vBVwv3+kPrxbNyfo48cB5cc5/4tq5zlJGas/qw8XNBE="; 43 | }) { inherit (pkgs.stdenv.hostPlatform) system; }).zigbee2mqtt; 44 | 45 | config = 46 | { homeassistant = true; 47 | permit_join = true; 48 | mqtt = { 49 | base_topic = "zigbee2mqtt"; 50 | server = "mqtt://localhost:1883"; 51 | }; 52 | 53 | frontend = 54 | { port = 8456; 55 | host = "0.0.0.0"; 56 | }; 57 | 58 | serial.port = "tcp://\${XIAOMI_HUB_IP}:8888"; 59 | serial.adapter = "ezsp"; 60 | 61 | devices = "devices.yaml"; 62 | groups = "groups.yaml"; 63 | log_level = "debug"; 64 | }; 65 | }; 66 | 67 | services.home-assistant = { 68 | enable = true; 69 | envsubst = true; 70 | customComponents = { 71 | xiaomi_gateway3 = pkgs.fetchFromGitHub { 72 | owner = "AlexxIT"; 73 | repo = "XiaomiGateway3"; 74 | rev = "v1.6.5"; 75 | sha256 = "sha256-RSIJqsbgnktl7zNaxAKUoMjbkrJ1aJTej0vjlCgstJ8="; 76 | } + "/custom_components/xiaomi_gateway3"; 77 | }; 78 | config = 79 | { default_config = {}; 80 | http.server_port = "8123"; 81 | logger.default = "info"; 82 | homeassistant = 83 | { name = "Home"; 84 | latitude = "\${LATITUDE}"; 85 | longitude = "\${LONGTIDE}"; 86 | elevation = "\${ELEVATION}"; 87 | # currency = "EUR"; 88 | unit_system = "metric"; 89 | time_zone = "\${TIMEZONE}"; 90 | internal_url = "http://localhost:8123/"; 91 | }; 92 | frontend.themes = 93 | { }; 94 | }; 95 | package = 96 | (pkgs.home-assistant.override 97 | { extraComponents = 98 | [ "http" 99 | "homeassistant" 100 | "image" 101 | "person" 102 | "cloud" 103 | "onboarding" 104 | "frontend" 105 | "safe_mode" 106 | "met" 107 | "zha" 108 | "mobile_app" 109 | "dhcp" 110 | "logbook" 111 | "history" 112 | "ssdp" 113 | "mqtt" 114 | ]; 115 | extraPackages = ps: with ps; 116 | [ xmodem 117 | ]; 118 | }).overridePythonAttrs (old: 119 | { doCheck = false; 120 | }); 121 | }; 122 | }; 123 | }); 124 | } 125 | -------------------------------------------------------------------------------- /examples/hydra/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-hydra"; 14 | config = ({ pkgs, config, ... }: 15 | { 16 | config = { 17 | dumb-init = { 18 | enable = true; 19 | type.services = { }; 20 | }; 21 | nix = { 22 | loadNixDb = true; 23 | persistNix = "/nix-persist"; 24 | config = { 25 | experimental-features = [ "nix-command" "flakes" ]; 26 | sandbox = true; 27 | trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; 28 | substituters = [ "https://cache.nixos.org/" ]; 29 | }; 30 | }; 31 | services.hydra = { 32 | enable = true; 33 | hydraURL = "http://localhost:3000/"; 34 | notificationSender = "root@example.org"; 35 | useSubstitutes = true; 36 | }; 37 | services.postgresql.package = pkgs.postgresql_12; 38 | services.socklog = { 39 | enable = true; 40 | unix = "/dev/log"; 41 | }; 42 | }; 43 | } 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /examples/jmusicbot/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-jmusicbot"; 14 | config = ({ pkgs, ... }: 15 | { 16 | dumb-init = { 17 | enable = true; 18 | type.services = { }; 19 | }; 20 | init.services.jmusicbot = { 21 | shutdownOnExit = true; 22 | }; 23 | 24 | services.jmusicbot = { 25 | enable = true; 26 | 27 | config = { 28 | prefix = "sudo"; 29 | token = "\${BOT_TOKEN}"; 30 | owner = "\${BOT_OWNER}"; 31 | }; 32 | }; 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /examples/minecraft/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-minecraft"; 14 | config = ({ pkgs, config, ... }: 15 | with pkgs.lib; 16 | { 17 | config = { 18 | dumb-init = { 19 | enable = true; 20 | type.services = { }; 21 | }; 22 | init.services.minecraft = { 23 | shutdownOnExit = true; 24 | }; 25 | 26 | services.minecraft = { 27 | enable = true; 28 | eulaAccept = true; 29 | 30 | forgeZipFile = builtins.fetchurl { 31 | url = "https://media.forgecdn.net/files/3551/162/SIMPLE-SERVER-FILES-1.8.12.zip"; 32 | sha256 = "sha256:16w4874vbc8zab6czixmx62i5hxfv1zkjcbfz9djmhwwa8inw02l"; 33 | }; 34 | forgeFetchedHash = "sha256-58HAjgrbtVb62vJKdfzXTIJRSycP1cDnp4h5/mnIwtY="; 35 | 36 | forgeConfigOverrides = {}; 37 | }; 38 | }; 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /examples/nginx/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-nginx"; 14 | config = ({ pkgs, config, ... }: 15 | { 16 | config = { 17 | dumb-init = { 18 | enable = true; 19 | type.services = { }; 20 | }; 21 | init.services.nginx = { 22 | shutdownOnExit = true; 23 | ensureSomething.link."documentRoot" = { 24 | src = "${pkgs.apacheHttpd}/htdocs"; 25 | dst = "/var/www"; 26 | }; 27 | }; 28 | services.nginx = { 29 | enable = true; 30 | envsubst = true; 31 | configuration = [ 32 | { 33 | daemon = "off"; 34 | worker_processes = 2; 35 | user = "nginx"; 36 | 37 | events."" = { 38 | use = "epoll"; 39 | worker_connections = 128; 40 | }; 41 | 42 | error_log = [ "/dev/stderr" "info" ]; 43 | pid = "/nginx.pid"; 44 | 45 | http."" = { 46 | server_tokens = "off"; 47 | include = "${pkgs.nginx}/conf/mime.types"; 48 | charset = "utf-8"; 49 | 50 | access_log = [ "/dev/stdout" "combined" ]; 51 | 52 | server."" = { 53 | server_name = "localhost"; 54 | listen = "0.0.0.0:80"; 55 | 56 | location."/var/www" = { 57 | root = "html"; 58 | }; 59 | }; 60 | }; 61 | } 62 | ]; 63 | }; 64 | }; 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /examples/nix/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-nix"; 14 | 15 | config = ({ pkgs, ... }: { 16 | dumb-init = { 17 | enable = true; 18 | type.shell = { }; 19 | }; 20 | nix = { 21 | enable = true; 22 | package = pkgs.nixFlakes; 23 | config = { 24 | experimental-features = [ "nix-command" "flakes" ]; 25 | sandbox = false; 26 | }; 27 | }; 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /examples/pantalaimon/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-pantalaimon"; 14 | config = ({ pkgs, ... }: 15 | { 16 | dumb-init = { 17 | enable = true; 18 | type.services = { }; 19 | }; 20 | init.services.pantalaimon = { 21 | shutdownOnExit = true; 22 | }; 23 | 24 | services.pantalaimon = { 25 | enable = true; 26 | 27 | package = (pkgs.pantalaimon.override 28 | { enableDbusUi = false; }).overrideAttrs (old: { 29 | version = "0.10.2"; 30 | src = pkgs.fetchFromGitHub { 31 | owner = "matrix-org"; 32 | repo = "pantalaimon"; 33 | rev = "0.10.2"; 34 | sha256 = "sha256-sjaJomKMKSZqLlKWTG7Oa87dXa5SnGQlVnrdS707A1w="; 35 | }; 36 | patches = [ ]; 37 | }); 38 | 39 | config = { 40 | Default = 41 | { 42 | LogLevel = "Debug"; 43 | SSL = "True"; 44 | Notifications = "Off"; 45 | }; 46 | 47 | Clockwork = 48 | { 49 | Homeserver = "https://matrix.org"; 50 | ListenAddress = "0.0.0.0"; 51 | ListenPort = 80; 52 | SSL = "False"; 53 | }; 54 | }; 55 | }; 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /examples/php-fpm/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, nixpkgs }: 10 | nglib.makeSystem { 11 | inherit nixpkgs; 12 | system = "x86_64-linux"; 13 | name = "nixng-php-fpm"; 14 | config = ({ pkgs, config, ... }: 15 | { 16 | config = { 17 | dumb-init = { 18 | enable = true; 19 | type.services = { }; 20 | }; 21 | 22 | init.services.apache2 = { 23 | shutdownOnExit = true; 24 | ensureSomething.link."documentRoot" = { 25 | src = ./documentRoot; 26 | dst = "/var/www"; 27 | }; 28 | }; 29 | 30 | services.php-fpm = { 31 | pools = { 32 | main = { 33 | createUserGroup = false; 34 | fpmSettings = { 35 | "pm" = "dynamic"; 36 | "pm.max_children" = 75; 37 | "pm.start_servers" = 10; 38 | "pm.min_spare_servers" = 5; 39 | "pm.max_spare_servers" = 20; 40 | "pm.max_requests" = 500; 41 | }; 42 | }; 43 | }; 44 | }; 45 | 46 | services.apache2 = { 47 | enable = true; 48 | envsubst = true; 49 | configuration = [ 50 | { 51 | LoadModule = [ 52 | [ "mpm_event_module" "modules/mod_mpm_event.so" ] 53 | [ "log_config_module" "modules/mod_log_config.so" ] 54 | [ "unixd_module" "modules/mod_unixd.so" ] 55 | [ "authz_core_module" "modules/mod_authz_core.so" ] 56 | [ "dir_module" "modules/mod_dir.so" ] 57 | [ "mime_module" "modules/mod_mime.so" ] 58 | [ "proxy_module" "modules/mod_proxy.so" ] 59 | [ "proxy_fcgi_module" "modules/mod_proxy_fcgi.so" ] 60 | ]; 61 | } 62 | { 63 | Listen = "0.0.0.0:80"; 64 | 65 | ServerRoot = "/var/www"; 66 | ServerName = "blowhole"; 67 | PidFile = "/httpd.pid"; 68 | 69 | DocumentRoot = "/var/www"; 70 | 71 | User = "www-data"; 72 | Group = "www-data"; 73 | } 74 | 75 | { 76 | ErrorLog = "/dev/stderr"; 77 | TransferLog = "/dev/stdout"; 78 | 79 | LogLevel = "info"; 80 | } 81 | 82 | { 83 | AddType = [ 84 | [ "image/svg+xml" "svg" "svgz" ] 85 | ]; 86 | AddEncoding = [ "gzip" "svgz" ]; 87 | 88 | TypesConfig = "${pkgs.apacheHttpd}/conf/mime.types"; 89 | } 90 | 91 | { 92 | Directory = { 93 | "/" = { 94 | Require = [ "all" "denied" ]; 95 | Options = "SymlinksIfOwnerMatch"; 96 | }; 97 | }; 98 | 99 | VirtualHost = { 100 | "*:80" = { 101 | ProxyPassMatch = 102 | [ 103 | "^/(.*\.php(/.*)?)$" 104 | "unix:${config.services.php-fpm.pools.main.socket}|fcgi://localhost/var/www/" 105 | ]; 106 | 107 | Directory = { 108 | "/var/www" = { 109 | Require = [ "all" "granted" ]; 110 | Options = [ "-Indexes" "+FollowSymlinks" ]; 111 | DirectoryIndex = "\${DIRECTORY_INDEX:-index.html}"; 112 | }; 113 | }; 114 | }; 115 | }; 116 | } 117 | ]; 118 | }; 119 | }; 120 | }); 121 | } 122 | -------------------------------------------------------------------------------- /examples/php-fpm/documentRoot/index.php: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | // 3 | // SPDX-License-Identifier: MPL-2.0 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/postfix/test-mail.sh: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { 10 | cat < 13 | RCPT TO: 14 | DATA 15 | Subject: Hello 16 | 17 | hello world 18 | . 19 | 20 | EOF 21 | 22 | sleep 1 23 | } | tee /dev/tty | telnet localhost 1025 24 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1641244400, 6 | "narHash": "sha256-8i4oasWEz/2y9U+F1XU15jfwSbd5YOEBh2tyBBm/W8E=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "c6019d8efb5530dcf7ce98086b8e091be5ff900a", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "ref": "nixos-21.11", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /flake.lock.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | SPDX-License-Identifier: CC0-1.0 4 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { 10 | inputs = { 11 | nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-21.11"; 12 | }; 13 | 14 | outputs = { nixpkgs, self }: 15 | let 16 | supportedSystems = [ "x86_64-linux" "i386-linux" "aarch64-linux" ]; 17 | forAllSystems' = nixpkgs.lib.genAttrs; 18 | forAllSystems = forAllSystems' supportedSystems; 19 | pkgsForSystem = system: 20 | import nixpkgs { inherit system; overlays = [ self.overlay ]; }; 21 | in 22 | { 23 | nglib = 24 | lib: 25 | let this = 26 | { makeSystem = import ./lib/make-system.nix { nglib = this; inherit (self) overlay; }; 27 | dag = import ./lib/dag.nix { inherit lib; }; 28 | generators = import ./lib/generators.nix { inherit lib; }; 29 | mkDefaultRec = lib.mapAttrsRecursive (_: v: lib.mkDefault v); 30 | }; 31 | in this; 32 | 33 | examples = import ./examples { inherit nixpkgs; inherit (self) nglib; }; 34 | 35 | overlay = import ./overlay; 36 | packages = forAllSystems pkgsForSystem; 37 | 38 | devShell = forAllSystems (system: 39 | let pkgs = pkgsForSystem system; 40 | in 41 | pkgs.mkShell { 42 | nativeBuildInputs = with pkgs; 43 | [ 44 | nixpkgs-fmt 45 | rnix-lsp 46 | dhall 47 | reuse 48 | ]; 49 | }); 50 | 51 | hydraJobs = { 52 | examples = nixpkgs.lib.mapAttrs (n: v: v.config.system.build.toplevel) self.examples; 53 | }; 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /lib/dag.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { lib }: 10 | import (builtins.fetchurl { 11 | url = "https://raw.githubusercontent.com/nix-community/home-manager/45abf3d38a2b51c00c347cab6950f3734e023bba/modules/lib/dag.nix"; 12 | sha256 = "sha256-NN9iKanf86D1MH9Nx8nsQj9T2+Poy9XeW9pLcZIyFHU="; 13 | }) { inherit lib; } 14 | -------------------------------------------------------------------------------- /lib/generators.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { lib }: 10 | with lib; 11 | rec { 12 | toApache = cfg: 13 | if isAttrs cfg then 14 | concatStringsSep "\n" 15 | (mapAttrsToList 16 | (name: value: 17 | if isString value then 18 | "${name} ${value}" 19 | else if isInt value then 20 | "${name} ${toString value}" 21 | else if isStorePath value then 22 | "${name} ${toString value}" 23 | else if isList value then 24 | if all (x: isString x) value then 25 | "${name} ${concatStringsSep " " value}" 26 | else if all (x: isInt x) value then 27 | "${name} ${concatStringsSep " " (toString value)}" 28 | else if all (x: isStorePath x) value then 29 | "${name} ${concatStringsSep " " (toString value)}" 30 | else if all (x: isList x) value then 31 | concatStringsSep "\n" 32 | (map (p: "${name} ${concatStringsSep " " p}") value) 33 | else 34 | abort "Unsupported type in ApacheHTTPD configuration attrset!" 35 | else if isAttrs value then 36 | concatStringsSep "\n" 37 | (mapAttrsToList 38 | (an: av: 39 | '' 40 | <${name} ${an}> 41 | ${toApache av} 42 | 43 | '') 44 | value) 45 | else 46 | abort "Unsupported type in ApacheHTTPD configuration attrset!" 47 | ) 48 | cfg) 49 | else if isList cfg then 50 | concatMapStringsSep "\n" 51 | (x: 52 | if isAttrs x then 53 | toApache x 54 | else if isString x then 55 | x 56 | else 57 | abort "Unsupported type in ApacheHTTPD configuration attrset!" 58 | ) 59 | cfg 60 | else 61 | abort "Unsupported type in ApacheHTTPD configuration attrset!"; 62 | 63 | toNginx = cfg: 64 | if isAttrs cfg then 65 | concatStringsSep "\n" 66 | (mapAttrsToList 67 | (name: value: 68 | if isString value then 69 | "${name} ${value};" 70 | else if isInt value then 71 | "${name} ${toString value};" 72 | else if isStorePath value then 73 | "${name} ${toString value};" 74 | else if isList value then 75 | if all (x: isString x) value then 76 | "${name} ${concatStringsSep " " value};" 77 | else if all (x: isInt x) value then 78 | "${name} ${concatStringsSep " " (toString value)};" 79 | else if all (x: isStorePath x) value then 80 | "${name} ${concatStringsSep " " (toString value)};" 81 | else if all (x: isList x) value then 82 | concatStringsSep "\n" 83 | (map (p: "${name} ${concatStringsSep " " p};") value) 84 | else 85 | abort "Unsupported type in Nginx configuration attrset!" 86 | else if isAttrs value then 87 | concatStringsSep "\n" 88 | (mapAttrsToList 89 | (an: av: 90 | '' 91 | ${name} ${an} { 92 | ${toNginx av} 93 | } 94 | '') 95 | value) 96 | else 97 | abort "Unsupported type in Nginx configuration attrset!" 98 | ) 99 | cfg) 100 | else if isList cfg then 101 | concatMapStringsSep "\n" 102 | (x: 103 | if isAttrs x then 104 | toNginx x 105 | else if isString x then 106 | x 107 | else 108 | abort "Unsupported type in Nginx configuration attrset!" 109 | ) 110 | cfg 111 | else 112 | abort "Unsupported type in Nginx configuration attrset!"; 113 | 114 | toDovecot = cfg: 115 | if isAttrs cfg then 116 | concatStringsSep "\n" 117 | (mapAttrsToList 118 | (name: value: 119 | if isNull value then 120 | "" 121 | else if isString value then 122 | "${name} = ${value}" 123 | else if isInt value then 124 | "${name} = ${toString value}" 125 | else if isStorePath value then 126 | "${name} = ${toString value}" 127 | else if isBool value then 128 | if value then 129 | "${name} = yes" 130 | else 131 | "${name} = no" 132 | 133 | else if isAttrs value then 134 | concatStringsSep "\n" 135 | (mapAttrsToList 136 | (n: v: 137 | '' 138 | ${name} ${if n == "" then n else "\"" + n + "\""} { 139 | '' 140 | + 141 | toDovecot v 142 | + 143 | '' 144 | 145 | } 146 | '' 147 | ) 148 | value) 149 | else if isList value && name != "include'" && name != "include_try'" then 150 | "${name} = " + concatMapStringsSep ", " 151 | (x: 152 | if isString x then 153 | x 154 | else if isInt x then 155 | toString x 156 | else if isStorePath x then 157 | toString x 158 | else if isBool x then 159 | if value then 160 | "yes" 161 | else 162 | "no" 163 | else 164 | abort "Unsupported type in Dovecot configuration attrset!" 165 | ) 166 | value 167 | else if isList value && name == "include'" then 168 | concatMapStringsSep "\n" 169 | (x: 170 | "include! " + x 171 | ) 172 | value 173 | else if isList value && name == "include_try'" then 174 | concatMapStringsSep "\n" 175 | (x: 176 | "include_try! " + x 177 | ) 178 | value 179 | else 180 | abort "Unsupported type in Dovecot configuration attrset!" 181 | ) 182 | cfg) 183 | else 184 | abort "Unsupported type in Dovecot configuration attrset!"; 185 | 186 | postfix = { 187 | toMainCnf = cfg: 188 | if isAttrs cfg then 189 | concatStringsSep "\n" 190 | (mapAttrsToList 191 | (name: value: 192 | if isNull value then 193 | "" 194 | else if isString value then 195 | "${name} = ${value}" 196 | else if isInt value then 197 | "${name} = ${toString value}" 198 | else if isStorePath value then 199 | "${name} = ${toString value}" 200 | else if isBool value then 201 | if value then 202 | "${name} = yes" 203 | else 204 | "${name} = no" 205 | else if isList value then 206 | "${name} = " + concatMapStringsSep ", " 207 | (x: 208 | if isString x then 209 | x 210 | else if isInt x then 211 | toString x 212 | else if isStorePath x then 213 | toString x 214 | else if isBool x then 215 | if value then 216 | "yes" 217 | else 218 | "no" 219 | else 220 | abort "Unsupported type in Postfix main configuration attrset!" 221 | ) 222 | value 223 | else 224 | abort "Unsupported type in Postfix main configuration attrset!" 225 | ) 226 | cfg) 227 | else 228 | abort "Unsupported type in Postfix main configuration attrset!"; 229 | }; 230 | 231 | php = { 232 | ini = cfg: 233 | concatStringsSep "\n" (mapAttrsToList 234 | (name: value: 235 | "${name} = ${toString value}" 236 | ) 237 | cfg); 238 | fpm = env: cfg: header: 239 | concatStringsSep "\n" 240 | ([ "[${header}]" ] 241 | ++ (mapAttrsToList 242 | (name: value: 243 | "${name} = ${toString value}" 244 | ) 245 | cfg) 246 | ++ (mapAttrsToList 247 | (name: value: 248 | "env[${name}] = ${toString value}" 249 | ) 250 | env) 251 | ++ [ "" ]); 252 | }; 253 | } 254 | -------------------------------------------------------------------------------- /lib/make-system.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | # These arguments are provided by the overarching NixNG repository and are not user confugurable. 10 | { nglib 11 | , overlay 12 | }: 13 | # These arguments are user configurable 14 | { nixpkgs 15 | , name 16 | , system 17 | , config 18 | }: 19 | with nixpkgs.lib; 20 | let 21 | defaultModules = [ 22 | ../modules/runit 23 | ../modules/dumb-init 24 | ../modules/initrd 25 | ../modules/init.nix 26 | ../modules/system.nix 27 | ../modules/assertions.nix 28 | ../modules/bootloader 29 | ../modules/nix.nix 30 | 31 | ../modules/security/ca.nix 32 | 33 | ../modules/misc/iana.nix 34 | 35 | ../modules/environment.nix 36 | ../modules/users.nix 37 | ../modules/ids.nix 38 | 39 | ../modules/services/apache2-nixos.nix 40 | ../modules/services/nginx.nix 41 | ../modules/services/gitea.nix 42 | ../modules/services/getty.nix 43 | ../modules/services/socklog.nix 44 | ../modules/services/crond.nix 45 | ../modules/services/hydra.nix 46 | ../modules/services/postgresql.nix 47 | ../modules/services/mysql.nix 48 | ../modules/services/certbot.nix 49 | ../modules/services/postfix.nix 50 | ../modules/services/dovecot.nix 51 | ../modules/services/pantalaimon.nix 52 | ../modules/services/jmusicbot.nix 53 | ../modules/services/php-fpm.nix 54 | ../modules/services/minecraft.nix 55 | ../modules/services/home-assistant.nix 56 | ../modules/services/zigbee2mqtt.nix 57 | ../modules/services/mosquitto.nix 58 | ({ ... }: { 59 | system.name = name; 60 | }) 61 | ]; 62 | 63 | evaledModules = evalModules 64 | { 65 | modules = defaultModules ++ [ 66 | config 67 | ({ ... }: 68 | { 69 | _module.args = { 70 | pkgs = import nixpkgs { inherit system; overlays = [ overlay ]; }; 71 | inherit system nglib; 72 | }; 73 | } 74 | ) 75 | ]; 76 | }; 77 | 78 | failedAssertions = map (x: x.message) (filter (x: !x.assertion) evaledModules.config.assertions); 79 | configValid = 80 | if failedAssertions != [ ] then 81 | throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}" 82 | else 83 | evaledModules.config; 84 | in 85 | evaledModules // { config = configValid; } 86 | -------------------------------------------------------------------------------- /modules/assertions.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { lib, ... }: 10 | with lib; 11 | let 12 | cfg = config.assertions; 13 | in 14 | { 15 | options.assertions = mkOption { 16 | description = "List of assertions"; 17 | type = types.listOf types.unspecified; 18 | default = [ ]; 19 | example = [ 20 | { 21 | assertion = 1 == 2; 22 | message = "The universe broke!"; 23 | } 24 | ]; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /modules/bootloader/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { config, lib, ... }: 10 | with lib; 11 | let 12 | cfg = config.bootloader; 13 | 14 | initrdAlgos = lib.genAttrs [ 15 | "gzip" 16 | "bzip2" 17 | "lzma" 18 | "xz" 19 | "lzo" 20 | "lz4" 21 | ] 22 | (algo: "CONFIG_RD_${lib.toUpper algo}"); 23 | 24 | filesystems = lib.genAttrs [ 25 | "ext4" 26 | "ext3" 27 | "vfat" 28 | "xfs" 29 | "btrfs" 30 | "f2fs" 31 | "zfs" 32 | ] 33 | (fs: 34 | if fs == "zfs" then 35 | throw "Not supported :) would need a patch" 36 | else 37 | "CONFIG_${lib.toUpper fs}_FS" 38 | ); 39 | in 40 | { 41 | options.bootloader = { 42 | enable = mkEnableOption "Enable the bootloader"; 43 | kernelExtraConfig = mkOption { 44 | description = ""; 45 | type = types.attrsOf (types.enum [ "y" "n" "m" ]); 46 | default = { }; 47 | }; 48 | 49 | initrdCompression = mkOption { 50 | description = "Supported compression algorithms for initrd"; 51 | type = types.listOf (types.enum (builtins.attrNames initrdAlgos)); 52 | default = [ ]; 53 | }; 54 | 55 | filesystems = mkOption { 56 | description = "Supported filesystems for initrd"; 57 | type = types.listOf (types.enum (builtins.attrNames filesystems)); 58 | default = [ ]; 59 | }; 60 | }; 61 | 62 | config.bootloader = mkIf cfg.enable { 63 | kernelExtraConfig = 64 | (builtins.listToAttrs 65 | (map 66 | (algo: 67 | { name = initrdAlgos."${algo}"; value = "y"; } 68 | ) 69 | cfg.initrdCompression 70 | ++ map 71 | (fs: 72 | { name = filesystems."${fs}"; value = "y"; } 73 | ) 74 | cfg.filesystems)); 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /modules/dumb-init/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, config, ... }: 10 | with lib; 11 | let 12 | cfg = config.dumb-init; 13 | cfgRunit = config.runit; 14 | cfgSystem = config.system; 15 | cfgUsers = config.users; 16 | cfgNix = config.nix; 17 | 18 | userShell = 19 | let 20 | user = config.users.users."${cfg.type.shell.user}"; 21 | in 22 | if user.useDefaultShell then 23 | config.users.defaultUserShell 24 | else 25 | user.shell; 26 | 27 | sigellConfig = overrides: 28 | pkgs.writeText "sigell.json" (builtins.toJSON (cfg.sigell // overrides)); 29 | in 30 | { 31 | options.dumb-init = { 32 | enable = mkEnableOption "Enable the dumb-init init system"; 33 | 34 | package = mkOption { 35 | description = "The dumb-init package to use"; 36 | type = types.package; 37 | default = pkgs.dumb-init; 38 | }; 39 | 40 | sigell = mkOption { 41 | description = '' 42 | A signal rewriting program, which allows to redirect, 43 | rewrite and handle signals easily 44 | ''; 45 | type = with types; nullOr (attrs); 46 | default = null; 47 | }; 48 | 49 | type = mkOption { 50 | description = "Which type of stage 2 init to run"; 51 | type = types.submodule { 52 | options = { 53 | services = mkOption { 54 | description = "Run the runit stage-2 script to start runsvdir and all the services."; 55 | type = with types; nullOr (submodule { }); 56 | default = null; 57 | }; 58 | 59 | shell = mkOption { 60 | description = "Run a bash shell, without any services."; 61 | type = with types; nullOr (submodule { 62 | options = { 63 | user = mkOption { 64 | description = "Which user to start the shell under."; 65 | type = str; 66 | default = "root"; 67 | }; 68 | }; 69 | }); 70 | default = null; 71 | }; 72 | }; 73 | }; 74 | }; 75 | }; 76 | 77 | config = { 78 | init = mkMerge [ 79 | { 80 | availableInits = [ "dumb-init" ]; 81 | } 82 | (mkIf cfg.enable { 83 | type = "dumb-init"; 84 | shutdown = pkgs.writeShellScript "dum-init-shutdown" 85 | '' 86 | kill -SIGTERM 1 87 | ''; 88 | script = 89 | let 90 | runit = pkgs.writeShellScript "init" 91 | '' 92 | export PATH=${pkgs.busybox}/bin 93 | _system_config="@systemConfig@" 94 | 95 | "$_system_config/activation" 96 | exec ${cfg.package}/bin/dumb-init -- \ 97 | ${sigell [ "${cfgRunit.stages.stage-2}" ]} 98 | ''; 99 | shell = pkgs.writeShellScript "init" 100 | '' 101 | export PATH=${pkgs.busybox}/bin:${pkgs.bash}/bin 102 | _system_config="@systemConfig@" 103 | 104 | "$_system_config/activation" 105 | . /etc/profile 106 | exec ${cfg.package}/bin/dumb-init -- \ 107 | ${sigell ["su" "${cfg.type.shell.user}" "-c" "${userShell} \"$@\"" ]} 108 | ''; 109 | sigell = cmd: 110 | if cfg.sigell != null then 111 | "${pkgs.sigell}/bin/sigell ${sigellConfig { command = cmd; }}" 112 | else 113 | concatStringsSep " " cmd; 114 | in 115 | if cfg.type.services != null then 116 | runit 117 | else if cfg.type.shell != null then 118 | shell 119 | else 120 | throw "Assertion should have caught this, only one dumb-init type selected."; 121 | }) 122 | ]; 123 | 124 | assertions = [ 125 | { 126 | assertion = count (x: x) (mapAttrsToList (n: v: v != null) cfg.type) == 1; 127 | message = "Please select exactly one dumb-init type."; 128 | } 129 | ] ++ (optional (cfg.type.shell != null) 130 | { 131 | assertion = cfgUsers.users ? "${cfg.type.shell.user}"; 132 | message = "User ${cfg.type.shell.user} does not exist!"; 133 | }); 134 | }; 135 | } 136 | -------------------------------------------------------------------------------- /modules/environment.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, config, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.environment; 13 | profileScript = pkgs.writeShellScript "profile" cfg.shell.profile; 14 | in 15 | { 16 | options.environment = { 17 | variables = mkOption { 18 | default = { }; 19 | example = { EDITOR = "vim"; BROWSER = "firefox"; }; 20 | type = with types; attrsOf (either str (listOf str)); 21 | apply = x: concatStringsSep ":" 22 | (mapAttrsToList (n: v: "${n}=" + (if isList v then concatStringsSep ":" v else v)) x); 23 | }; 24 | 25 | shell = { 26 | profile = mkOption { 27 | description = '' 28 | Shell script fragments, concataned into /etc/profile. 29 | ''; 30 | type = with types; listOf str; 31 | apply = x: concatStringsSep "\n" x; 32 | default = [ ]; 33 | }; 34 | }; 35 | 36 | createBaseEnv = mkOption { 37 | description = '' 38 | Create /bin/sh, /usr/bin/env, /var/empty, and /tmp. 39 | ''; 40 | type = types.bool; 41 | default = true; 42 | }; 43 | 44 | systemPackages = mkOption { 45 | description = "Packages globally added to PATH"; 46 | default = [ ]; 47 | type = with types; listOf package; 48 | }; 49 | }; 50 | 51 | config = { 52 | environment.shell.profile = [ 53 | '' 54 | export ${cfg.variables} 55 | export PATH="$PATH"':${makeBinPath cfg.systemPackages}' 56 | '' 57 | ]; 58 | 59 | system.activation.shellProfile = nglib.dag.dagEntryAnywhere '' 60 | export PATH=${pkgs.busybox}/bin 61 | 62 | mkdir -m 0755 -p /etc 63 | ln -sfn ${profileScript} /etc/.profile.tmp 64 | mv /etc/.profile.tmp /etc/profile # atomically replace /etc/profile 65 | ''; 66 | 67 | system.activation.createBaseEnv = mkIf cfg.createBaseEnv 68 | (nglib.dag.dagEntryAnywhere 69 | '' 70 | export PATH=${pkgs.busybox}/bin 71 | 72 | # Borrowed from NixOS therefore it's licensed under the MIT license 73 | #### Activation script snippet usrbinenv: 74 | _localstatus=0 75 | mkdir -m 0755 -p /usr/bin 76 | ln -sfn ${pkgs.busybox}/bin/env /usr/bin/.env.tmp 77 | mv /usr/bin/.env.tmp /usr/bin/env # atomically replace /usr/bin/env 78 | 79 | # Create the required /bin/sh symlink; otherwise lots of things 80 | # (notably the system() function) won't work. 81 | mkdir -m 0755 -p /bin 82 | ln -sfn "${pkgs.busybox}/bin/sh" /bin/.sh.tmp 83 | mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh 84 | 85 | mkdir -pm 0777 /tmp 86 | mkdir -pm 0555 /var/empty 87 | ''); 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /modules/ids.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { lib, ... }: 10 | with lib; 11 | { 12 | options.ids = { 13 | uids = mkOption { 14 | description = "A username to uid map, used for keeping track of assigned uids."; 15 | type = with types; attrsOf int; 16 | }; 17 | gids = mkOption { 18 | description = "A groupname to gid map, used for keeping track of assigned gids."; 19 | type = with types; attrsOf int; 20 | }; 21 | }; 22 | 23 | config = { 24 | ids.uids = { 25 | root = 0; 26 | postfix = 13; 27 | #postdrop = 14; 28 | dovecot = 46; 29 | dovenull = 47; 30 | www-data = 54; 31 | nginx = 60; 32 | postgres = 71; 33 | mysql = 84; 34 | hydra = 122; 35 | hydra-queue-runner = 235; 36 | hydra-www = 236; 37 | pantalaimon = 398; # might change! 38 | gitea = 399; # might change! 39 | jmusicbot = 400; 40 | mosquitto = 401; 41 | zigbee2mqtt = 402; 42 | home-assistant = 403; 43 | vmail = 5000; 44 | nobody = 65534; 45 | }; 46 | 47 | ids.gids = { 48 | root = 0; 49 | postfix = 13; 50 | postdrop = 14; 51 | dovecot = 46; 52 | dovenull = 47; 53 | www-data = 54; 54 | nginx = 60; 55 | postgres = 71; 56 | mysql = 84; 57 | hydra = 122; 58 | hydra-queue-runner = 235; 59 | hydra-www = 236; 60 | pantalaimon = 398; # might change! 61 | log = 399; 62 | jmusicbot = 400; 63 | mosquitto = 401; 64 | zigbee2mqtt = 402; 65 | home-assistant = 403; 66 | vmail = 5000; 67 | nogroup = 65534; 68 | }; 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /modules/initrd/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, config, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.initrd; 13 | in 14 | { 15 | options.initrd = { 16 | enable = mkEnableOption "Enable initrd as init"; 17 | }; 18 | 19 | config.init = mkMerge [ 20 | { 21 | availableInits = [ "initrd" ]; 22 | } 23 | (mkIf cfg.enable { 24 | type = "initrd"; 25 | script = nglib.writeSubstitutedShellScript { 26 | name = "init"; 27 | file = ./init.sh; 28 | substitutes = with pkgs; { 29 | inherit eudev bash busybox; 30 | }; 31 | }; 32 | }) 33 | ]; 34 | } 35 | -------------------------------------------------------------------------------- /modules/initrd/init.sh: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | # http://www.linuxfromscratch.org/blfs/view/svn/postlfs/initramfs.html 10 | 11 | export PATH=$PATH:@bash@/bin:@busybox@/bin:@eudev@/bin 12 | 13 | echo "Hello" 14 | 15 | problem() 16 | { 17 | printf "Encountered a problem!\n\nDropping you to a shell.\n\n" 18 | sh 19 | } 20 | 21 | do_mount_root() { 22 | mkdir /.root 23 | [ -n "$rootflags" ] && rootflags="$rootflags," 24 | rootflags="$rootflags$ro" 25 | 26 | case "$root" in 27 | /dev/* ) device=$root ;; 28 | UUID=* ) eval $root; device="/dev/disk/by-uuid/$UUID" ;; 29 | PARTUUID=*) eval $root; device="/dev/disk/by-partuuid/$PARTUUID" ;; 30 | LABEL=* ) eval $root; device="/dev/disk/by-label/$LABEL" ;; 31 | "" ) echo "No root device specified." ; problem ;; 32 | esac 33 | 34 | while [ ! -b "$device" ] ; do 35 | no_device $device 36 | problem 37 | done 38 | 39 | if ! mount -n -t "$rootfstype" -o "$rootflags" "$device" /.root ; then 40 | no_mount $device 41 | cat /proc/partitions 42 | while true ; do sleep 10000 ; done 43 | else 44 | echo "Successfully mounted device $root" 45 | fi 46 | } 47 | 48 | echo "Stage 1 commence" 49 | 50 | mkdir -p /dev /proc /sys /run 51 | mount -n -t devtmpfs devtmpfs /dev 52 | mount -n -t proc proc /proc 53 | mount -n -t sysfs sysfs /sys 54 | mount -n -t tmpfs tmpfs /run 55 | 56 | read -r cmdline < /proc/cmdline 57 | 58 | for param in $cmdline ; do 59 | case $param in 60 | init=*) init=${param#init=} ;; 61 | root=*) root=${param#root=} ;; 62 | rootdelay=*) rootdelay=${param#rootdelay=} ;; 63 | rootfstype=*) rootfstype=${param#rootfstype=} ;; 64 | rootflags=*) rootflags=${param#rootflags=} ;; 65 | noresume=*) noresume=true ;; 66 | ro=*) ro="ro" ;; 67 | rw=*) ro="rw" ;; 68 | esac 69 | done 70 | 71 | udevd --daemon --resolve-names=never 72 | udevadm trigger 73 | udevadm settle 74 | 75 | if [ -n "$rootdelay" ] ; then sleep "$rootdelay" ; fi 76 | 77 | bash 78 | -------------------------------------------------------------------------------- /modules/misc/iana.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, config, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.iana; 13 | in 14 | { 15 | options.iana = { 16 | enable = mkOption { 17 | description = "Enable /etc/services creation."; 18 | type = types.bool; 19 | default = true; 20 | }; 21 | 22 | package = mkOption { 23 | description = "iana package."; 24 | type = types.package; 25 | default = pkgs.iana-etc; 26 | }; 27 | }; 28 | 29 | config = { 30 | system.activation."iana" = nglib.dag.dagEntryAnywhere '' 31 | export PATH=${pkgs.busybox}/bin 32 | 33 | mkdir -p /etc/ 34 | ln -sf ${cfg.package}/etc/services /etc/services 35 | ln -sf ${cfg.package}/etc/protocols /etc/protocols 36 | ''; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /modules/nix.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, config, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.nix; 13 | 14 | nix = cfg.package.out; 15 | 16 | nixVersion = getVersion nix; 17 | 18 | isNix23 = versionAtLeast nixVersion "2.3pre"; 19 | 20 | parser = 21 | let 22 | valToString = v: 23 | if isString v then 24 | "${v}" 25 | else if isInt v then 26 | "${toString v}" 27 | else if isBool v then 28 | if v then 29 | "true" 30 | else 31 | "false" 32 | else if isList v then 33 | concatMapStringsSep " " (x: valToString x) v 34 | else 35 | abort "Invalid config, module system should have caught this!"; 36 | in 37 | config: 38 | concatStringsSep "\n" (mapAttrsToList 39 | (n: v: 40 | "${n} = ${valToString v}" 41 | ) 42 | config); 43 | in 44 | { 45 | options.nix = { 46 | enable = mkEnableOption "Enable Nix, add Nix the global path and creates the necessary folder structure."; 47 | 48 | package = mkOption { 49 | description = '' 50 | Which package to use for running Nix related commands, will also be added 51 | to the global system PATH, TODO. 52 | ''; 53 | type = types.package; 54 | default = pkgs.nix; 55 | }; 56 | 57 | buildUserCount = mkOption { 58 | description = '' 59 | How many build users, and groups should be created, if Nix runs out, 60 | increase this number. 61 | ''; 62 | type = types.int; 63 | default = 32; 64 | }; 65 | 66 | config = mkOption { 67 | description = '' 68 | Contents of nix.conf, represented using an attrset containing strings, bools, ints, or lists of strings, bools, or ints. 69 | ''; 70 | type = with types; attrsOf (oneOf [ str int bool (listOf (oneOf [ str int bool ])) ]); 71 | example = 72 | { 73 | sandbox = true; 74 | require-sigs = true; 75 | cores = 0; 76 | }; 77 | default = { }; 78 | apply = x: 79 | builtins.toFile "nix.conf" (parser x); 80 | }; 81 | 82 | loadNixDb = mkOption { 83 | description = '' 84 | Whether to create the registration of this closure, and to load it at 85 | activation time. Useful when bootstraping a system, such as containers. 86 | ''; 87 | type = types.bool; 88 | default = false; 89 | }; 90 | 91 | nixPath = mkOption { 92 | description = '' 93 | The Nix Path, basically channels. 94 | ''; 95 | type = with types; listOf str; 96 | default = [ 97 | "nixpkgs=${pkgs.path}" 98 | ]; 99 | }; 100 | 101 | persistNix = mkOption { 102 | description = '' 103 | Will copy the contents of the the included /nix to 104 | ''${persistNix}/nix/store. Then bind mount 105 | ''${persistNix}/nix/store over /nix. 106 | Can be used to persist /nix across container restarts. 107 | ''; 108 | type = with types; nullOr str; 109 | default = null; 110 | }; 111 | 112 | daemon = mkOption { 113 | description = '' 114 | Whether to start the Nix daemon, therefore run in multi-user or single-user mode. 115 | ''; 116 | type = types.bool; 117 | default = false; 118 | }; 119 | }; 120 | 121 | config = mkIf cfg.enable { 122 | system.createNixRegistration = mkIf cfg.loadNixDb true; 123 | system.activation.loadNixDb = mkIf cfg.loadNixDb 124 | (nglib.dag.dagEntryAfter [ "currentSystem" "users" ] 125 | '' 126 | export PATH=${pkgs.busybox}/bin:${cfg.package}/bin 127 | 128 | if [[ ! -d /nix/var/nix/db ]] ; then 129 | nix-store --init 130 | nix-store --load-db < /run/current-system/registration 131 | ls /nix/var/nix 132 | fi 133 | ''); 134 | 135 | system.activation.persistNix = mkIf (cfg.persistNix != null) 136 | (nglib.dag.dagEntryAfter [ "loadNixDb" ] 137 | '' 138 | export PATH=${pkgs.busybox}/bin:${cfg.package}/bin:${pkgs.utillinux}/bin 139 | 140 | mkdir -p ${cfg.persistNix} 141 | USER=root GROUP=root nix copy --no-check-sigs --all --to local?root=${cfg.persistNix} 142 | mount -o bind ${cfg.persistNix}/nix /nix 143 | ''); 144 | 145 | 146 | users = { 147 | users = mkMerge (map 148 | (x: 149 | { 150 | "nixbld${toString x}" = { 151 | uid = 30000 + x; 152 | group = "nixbld"; 153 | home = "/var/empty"; 154 | createHome = false; 155 | description = "Nix build user ${toString x}"; 156 | shell = "${pkgs.busybox}/bin/nologin"; 157 | }; 158 | }) 159 | (range 0 cfg.buildUserCount)); 160 | 161 | groups.nixbld.gid = 30000; 162 | }; 163 | 164 | environment.variables = { 165 | NIX_PATH = cfg.nixPath; 166 | NIX_REMOTE = mkIf cfg.daemon "daemon"; 167 | }; 168 | 169 | environment.systemPackages = [ cfg.package ]; 170 | 171 | nix.config = mkDefault { 172 | build-users-group = "nixbld"; 173 | max-jobs = "auto"; 174 | cores = 0; 175 | sandbox = true; 176 | extra-sandbox-paths = [ ]; 177 | substituters = [ "https://cache.nixos.org/" ]; 178 | trusted-substituters = [ ]; 179 | trusted-public-keys = 180 | [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; 181 | auto-optimise-store = false; 182 | require-sigs = true; 183 | allowed-users = "*"; 184 | builders = [ ]; 185 | 186 | system-features = mkDefault ( 187 | [ "nixos-test" "benchmark" "big-parallel" "kvm" ] ++ 188 | optionals (pkgs.hostPlatform.platform ? gcc.arch) ( 189 | # a builder can run code for `platform.gcc.arch` and inferior architectures 190 | [ "gccarch-${pkgs.hostPlatform.platform.gcc.arch}" ] ++ 191 | map (x: "gccarch-${x}") lib.systems.architectures.inferiors.${pkgs.hostPlatform.platform.gcc.arch} 192 | ) 193 | ); 194 | 195 | sandbox-fallback = mkIf isNix23 false; 196 | }; 197 | 198 | system.activation.nix = nglib.dag.dagEntryAnywhere '' 199 | export PATH=${pkgs.busybox}/bin 200 | 201 | install -m 0755 -d /nix/var/nix/{gcroots,profiles}/per-user 202 | 203 | # NixOS canonical location + Debian/Ubuntu/Arch/Gentoo compatibility. 204 | mkdir -m 0755 -p /etc/nix 205 | ln -sfn ${cfg.config} /etc/nix/.nix.conf.tmp 206 | mv /etc/nix/.nix.conf.tmp /etc/nix/nix.conf # atomically replace /etc/nix/nix.conf 207 | ''; 208 | 209 | init.services.nix-daemon = mkIf cfg.daemon { 210 | script = pkgs.writeShellScript "nix-daemon" '' 211 | chpst -b nix-daemon ${cfg.package}/bin/nix-daemon --daemon 212 | ''; 213 | enabled = true; 214 | }; 215 | }; 216 | } 217 | -------------------------------------------------------------------------------- /modules/runit/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, config, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.runit; 13 | cfgSystem = config.system; 14 | cfgInit = config.init; 15 | 16 | cfgNix = config.nix; 17 | in 18 | { 19 | options.runit = { 20 | enable = mkEnableOption "Enable runit"; 21 | 22 | pkg = mkOption { 23 | description = "runit package to use"; 24 | type = types.package; 25 | default = pkgs.runit; 26 | }; 27 | 28 | runtimeServiceDirectory = mkOption { 29 | description = "where runsvdir should create superwise and log directories for services"; 30 | type = types.path; 31 | default = "/service"; 32 | }; 33 | 34 | stages = mkOption { 35 | description = "runit stages"; 36 | default = { }; 37 | type = types.submodule { 38 | options = { 39 | stage-1 = mkOption { 40 | type = types.path; 41 | description = "runit stage 1"; 42 | default = pkgs.writeSubstitutedShellScript { 43 | name = "1"; 44 | file = ./stage-1.sh; 45 | substitutes = { 46 | activationScript = cfgSystem.activationScript; 47 | }; 48 | }; 49 | }; 50 | stage-2 = mkOption { 51 | type = types.path; 52 | description = "runit stage 2"; 53 | default = pkgs.writeSubstitutedShellScript { 54 | name = "2"; 55 | file = ./stage-2.sh; 56 | substitutes = { 57 | inherit (pkgs) runit findutils busybox utillinux; 58 | inherit (cfg) runtimeServiceDirectory; 59 | }; 60 | }; 61 | }; 62 | stage-3 = mkOption { 63 | type = types.path; 64 | description = "runit stage 3"; 65 | default = pkgs.writeSubstitutedShellScript { 66 | name = "3"; 67 | file = ./stage-3.sh; 68 | substitutes = { }; 69 | }; 70 | }; 71 | }; 72 | }; 73 | }; 74 | serviceDirectory = mkOption { 75 | description = "Generated service directory"; 76 | type = types.path; 77 | readOnly = true; 78 | }; 79 | }; 80 | 81 | config = { 82 | system.activation."runit" = nglib.dag.dagEntryAnywhere 83 | '' 84 | export PATH=${pkgs.findutils}/bin:${pkgs.busybox}/bin 85 | mkdir -p ${cfg.runtimeServiceDirectory} 86 | 87 | function linkFarm() { 88 | src="$1" 89 | dst="$2" 90 | 91 | find "$src" -mindepth 1 -type d -printf "%P\n" | xargs -I {} mkdir "$dst/{}" 92 | find "$src" -mindepth 1 -type f -printf "%P\n" | xargs -I {} ln -s "$src/{}" "$dst/{}" 93 | find "$src" -mindepth 1 -type l -printf "%P\n" | xargs -I {} cp "$src/{}" "$dst/{}" 94 | } 95 | 96 | linkFarm ${cfg.serviceDirectory} ${cfg.runtimeServiceDirectory} 97 | ''; 98 | 99 | runit = { 100 | serviceDirectory = pkgs.runCommandNoCCLocal "service-dir" { } '' 101 | mkdir $out 102 | ${concatStringsSep "\n" (mapAttrsToList (n: s: 103 | let 104 | run = pkgs.callPackage ./run.nix {} { inherit n s; }; 105 | finish = pkgs.callPackage ./finish.nix {} { inherit n s cfgInit; }; 106 | log = pkgs.callPackage ./log.nix {} { inherit n s; }; 107 | in 108 | assert s.dependencies == []; 109 | 110 | '' 111 | mkdir -p $out/${n}/log 112 | ln -s ${run} $out/${n}/run 113 | ln -s ${finish} $out/${n}/finish 114 | ln -s ${log} $out/${n}/log/run 115 | ${optionalString (!s.enabled) "touch $out/${n}/down"} 116 | '' 117 | ) cfgInit.services)} 118 | ''; 119 | }; 120 | 121 | init = mkMerge [ 122 | { 123 | availableInits = [ "runit" ]; 124 | } 125 | (mkIf cfg.enable { 126 | type = "runit"; 127 | shutdown = pkgs.writeShellScript "runit-shutdown" 128 | '' 129 | mkdir -p /etc/runit 130 | touch /etc/runit/stopit 131 | chmod 544 /etc/runit/stopit 132 | 133 | kill -SIGCONT 1 134 | ''; 135 | script = pkgs.writeShellScript "init" 136 | '' 137 | export PATH=${pkgs.busybox}/bin:${cfg.pkg}/bin \ 138 | _system_config="@systemConfig@" 139 | 140 | mkdir -p /etc/runit 141 | 142 | ln -sf ${cfg.stages.stage-1} /etc/runit/1 143 | ln -sf ${cfg.stages.stage-2} /etc/runit/2 144 | ln -sf ${cfg.stages.stage-3} /etc/runit/3 145 | 146 | exec runit-init 147 | ''; 148 | }) 149 | ]; 150 | }; 151 | } 152 | -------------------------------------------------------------------------------- /modules/runit/finish.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { lib 10 | , writeShellScript 11 | }: 12 | { n, s, cfgInit }: 13 | with lib; 14 | writeShellScript "${n}-finish" '' 15 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 16 | with cv; 17 | optionalString (!cv.persistent) '' 18 | if [[ -e ${dst} ]] ; then 19 | echo '${n}: removing non-presistent `${dst}`' 20 | rm -v ${dst} 21 | fi 22 | '' 23 | ) s.ensureSomething.link)} 24 | 25 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 26 | with cv; 27 | optionalString (!cv.persistent) '' 28 | if [[ -e ${dst} ]] ; then 29 | echo '${n}: removing non-presistent `${dst}`' 30 | rm -rv ${dst} 31 | fi 32 | '' 33 | ) s.ensureSomething.copy)} 34 | 35 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 36 | abort "linkFarm is not implemented yet in runit!" 37 | ) s.ensureSomething.linkFarm)} 38 | 39 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 40 | with cv; 41 | optionalString (!cv.persistent) '' 42 | if [[ -e ${dst} ]] ; then 43 | echo '${n}: removing non-persistent `${dst}`' 44 | rm -rv '${dst}' 45 | fi 46 | '' 47 | ) s.ensureSomething.exec)} 48 | 49 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 50 | with cv; 51 | optionalString (!cv.persistent) '' 52 | if [[ -e ${dst} ]] ; then 53 | echo '${n}: removing non-persistent `${dst}`' 54 | 55 | ${if (type == "directory") then 56 | "rm -rv ${dst}" 57 | else if (type == "file") then 58 | '' 59 | rm -v ${dst} 60 | '' 61 | else 62 | abort "Unsupported init create type, module system should have caught this!" 63 | } 64 | fi 65 | '' 66 | ) s.ensureSomething.create)} 67 | 68 | ( 69 | cd ${s.pwd} 70 | ${optionalString (s.environment != {}) "export ${concatStringsSep " " (mapAttrsToList (n: v: "${n}=${v}") s.environment)}"} 71 | ${optionalString (s.finish != null && !s.shutdownOnExit) "exec ${s.finish}"} 72 | ${optionalString (s.finish != null && s.shutdownOnExit) "${s.finish}"} 73 | ) 74 | 75 | ${optionalString (s.shutdownOnExit) ("exec ${cfgInit.shutdown}")} 76 | '' 77 | -------------------------------------------------------------------------------- /modules/runit/log.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { lib 10 | , utillinux 11 | , writeShellScript 12 | }: 13 | { n, s }: 14 | with lib; 15 | writeShellScript "${n}-log" '' 16 | ${ 17 | if s.log.file != null then 18 | with s.log.file; 19 | assert rotate == 0; 20 | '' 21 | cat > ${dst} 22 | '' 23 | else if s.log.syslog != null then 24 | with s.log.syslog; 25 | let 26 | inetDst = 27 | ''-n "$(echo "${dst}" | cut -d : -f 1)" -P "$(echo "${dst}" | cut -d : -f 2)"''; 28 | connection = 29 | if type == "uds" then 30 | "-u ${dst}" 31 | else if type == "udp" then 32 | ''-d ${inetDst}'' 33 | else if type == "tcp" then 34 | ''-T ${inetDst}'' 35 | else 36 | abort "Unknown log type, module system should have caught this!"; 37 | rfc5424 = 38 | optional (!time) "notime" 39 | ++ optional (!timeQuality) "notq" 40 | ++ optional (!host) "nohost"; 41 | in 42 | '' 43 | export PATH=${utillinux}/bin:$PATH 44 | logger ${connection} \ 45 | ${if rfc5424 == [] then "--rfc5424" else "--rfc5424=${concatStringsSep "," rfc5424}"} \ 46 | ${optionalString (tag != null) "-t ${tag}"} \ 47 | ${optionalString (priority != null) "-t ${priority}"} \ 48 | '' 49 | else 50 | "cat" # | sed -u 's/^/${n} => /' - busybox sed doesnt support unbuffered 51 | } 52 | '' 53 | -------------------------------------------------------------------------------- /modules/runit/run.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { lib 10 | , writeShellScript 11 | }: 12 | { n, s }: 13 | with lib; 14 | writeShellScript "${n}-run" '' 15 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 16 | with cv; 17 | '' 18 | if ! [[ -e ${dst} ]] ; then 19 | echo '${n}: linking `${src}` to `${dst}`' 20 | mkdir -p "$(dirname '${dst}')" 21 | ln -s '${src}' '${dst}' 22 | fi 23 | '' 24 | ) s.ensureSomething.link)} 25 | 26 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 27 | with cv; 28 | '' 29 | if ! [[ -e ${dst} ]] ; then 30 | echo '${n}: copying `${src}` to `${dst}`' 31 | mkdir -p "$(dirname '${dst}')" 32 | cp -r '${src}' '${dst}' 33 | fi 34 | '' 35 | ) s.ensureSomething.copy)} 36 | 37 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 38 | abort "linkFarm is not implemented yet in runit!" 39 | ) s.ensureSomething.linkFarm)} 40 | 41 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 42 | with cv; 43 | '' 44 | if ! [[ -e ${dst} ]] ; then 45 | echo '${n}: executing `${executable}` to create `${dst}`' 46 | mkdir -p "$(dirname '${dst}')" 47 | out=${dst} ${executable} 48 | 49 | if ! [[ -e ${dst} ]] ; then 50 | echo '${n}: executed `${executable}` but `${dst}` does not exist!' 51 | exit 1 52 | fi 53 | fi 54 | '' 55 | ) s.ensureSomething.exec)} 56 | 57 | ${concatStringsSep "\n" (mapAttrsToList (cn: cv: 58 | with cv; 59 | '' 60 | if ! [[ -e ${dst} ]] ; then 61 | echo '${n}: creating `${dst}`' 62 | 63 | ${if (type == "directory") then 64 | "mkdir -p ${dst}" 65 | else if (type == "file") then 66 | '' 67 | mkdir -p "$(dirname '${dst}')" 68 | touch ${dst} 69 | '' 70 | else 71 | abort "Unsupported init create type, module system should have caught this!" 72 | } 73 | 74 | chown ${owner} ${dst} 75 | ${optionalString (mode != null) "chmod ${mode} ${dst}"} 76 | fi 77 | '' 78 | ) s.ensureSomething.create)} 79 | 80 | ( 81 | cd ${s.pwd} 82 | ${optionalString (s.environment != {}) "export ${concatStringsSep " " (mapAttrsToList (n: v: "${n}=${v}") s.environment)}"} 83 | exec ${s.script} 84 | ) 85 | '' 86 | -------------------------------------------------------------------------------- /modules/runit/stage-1.sh: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | echo "<--- Stage 2.1 --->" 10 | 11 | mkdir /tmp 12 | 13 | # Run activation script for this system 14 | "$_system_config/activation" 15 | -------------------------------------------------------------------------------- /modules/runit/stage-2.sh: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | export PATH=@runit@/bin:@busybox@/bin 10 | 11 | echo "<--- Stage 2.2 --->" 12 | 13 | unset _system_config 14 | runsvdir @runtimeServiceDirectory@ 15 | -------------------------------------------------------------------------------- /modules/runit/stage-3.sh: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | echo "<--- Stage 2.3 --->" 10 | -------------------------------------------------------------------------------- /modules/security/ca.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { config, lib, pkgs, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.security.ca; 13 | 14 | cacertPackage = pkgs.cacert.override { 15 | blacklist = cfg.certificateBlacklist; 16 | }; 17 | 18 | caCertificates = pkgs.runCommand "ca-certificates.crt" 19 | { 20 | files = 21 | cfg.certificateFiles ++ 22 | [ (builtins.toFile "extra.crt" (concatStringsSep "\n" cfg.certificates)) ]; 23 | preferLocalBuild = true; 24 | } 25 | '' 26 | cat $files > $out 27 | ''; 28 | in 29 | { 30 | options.security.ca = { 31 | certificateFiles = mkOption { 32 | description = '' 33 | A list of files containing trusted root certificates in PEM 34 | format. These are concatenated to form 35 | /etc/ssl/certs/ca-certificates.crt, which is 36 | used by many programs that use OpenSSL, such as 37 | curl and git. 38 | ''; 39 | type = with types; listOf path; 40 | default = [ ]; 41 | }; 42 | 43 | certificates = mkOption { 44 | description = '' 45 | A list of trusted root certificates in PEM format. 46 | ''; 47 | type = with types; listOf str; 48 | default = [ ]; 49 | }; 50 | 51 | certificateBlacklist = mkOption { 52 | description = '' 53 | A list of blacklisted CA certificate names that won't be imported from 54 | the Mozilla Trust Store into 55 | /etc/ssl/certs/ca-certificates.crt. Use the 56 | names from that file. 57 | ''; 58 | type = with types; listOf str; 59 | default = [ ]; 60 | }; 61 | }; 62 | 63 | config = { 64 | security.ca.certificateFiles = [ "${cacertPackage}/etc/ssl/certs/ca-bundle.crt" ]; 65 | 66 | system.activation.cacerts = nglib.dag.dagEntryAnywhere '' 67 | export PATH=${pkgs.busybox}/bin 68 | 69 | # NixOS canonical location + Debian/Ubuntu/Arch/Gentoo compatibility. 70 | mkdir -m 0755 -p /etc/ssl/certs 71 | ln -sfn ${caCertificates} /etc/ssl/certs/.ca-certificates.crt.tmp 72 | mv /etc/ssl/certs/.ca-certificates.crt.tmp /etc/ssl/certs/ca-certificates.crt # atomically replace /etc/ssl/certs/ca-certificates.crt 73 | 74 | # CentOS/Fedora compatibility. 75 | mkdir -m 0755 -p /etc/pki/tls/certs 76 | ln -sfn ${caCertificates} /etc/pki/tls/certs/.ca-bundle.crt.tmp 77 | mv /etc/pki/tls/certs/.ca-bundle.crt.tmp /etc/pki/tls/certs/ca-bundle.crt # atomically replace /etc/pki/tls/certs/ca-bundle.crt 78 | ''; 79 | }; 80 | } 81 | -------------------------------------------------------------------------------- /modules/services/apache2-nixos.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.apache2; 13 | runtimeConfig = "/run/cfg/apache.cfg"; 14 | 15 | inherit (nglib.generators) toApache; 16 | in 17 | { 18 | options = { 19 | services.apache2 = { 20 | enable = mkEnableOption "Enable Apache2 http server"; 21 | package = mkOption { 22 | description = "Apache2 package"; 23 | type = types.package; 24 | default = pkgs.apacheHttpd; 25 | }; 26 | createUserGroup = mkOption { 27 | description = '' 28 | Whether to create the default user www-data 29 | and group www-data. 30 | ''; 31 | type = types.bool; 32 | default = true; 33 | }; 34 | envsubst = mkEnableOption "Run envsubst on the configuration file."; 35 | configuration = mkOption { 36 | description = "Apache2 configuration"; 37 | type = with types; 38 | let 39 | self = 40 | oneOf [ 41 | (attrsOf (oneOf [ 42 | str 43 | int 44 | (listOf (oneOf [ str int (listOf (oneOf [ str int ])) ])) 45 | (attrsOf self) 46 | ])) 47 | (listOf (oneOf [ str self ])) 48 | ]; 49 | in 50 | self // { description = "loop breaker"; }; 51 | }; 52 | }; 53 | }; 54 | 55 | 56 | config = mkIf cfg.enable 57 | { 58 | init.services.apache2 = 59 | let 60 | config = pkgs.writeText "apache2.cfg" (toApache cfg.configuration); 61 | in 62 | { 63 | script = pkgs.writeShellScript "apache2-run" 64 | (if cfg.envsubst then 65 | '' 66 | export PATH=${pkgs.envsubst}/bin:$PATH 67 | 68 | mkdir -p /run/cfg 69 | install -o www-data -g www-data -m 0440 /dev/null ${runtimeConfig} 70 | envsubst < ${config} > ${runtimeConfig} 71 | 72 | HOME=~www-data ${cfg.package}/bin/httpd \ 73 | -f ${runtimeConfig} -DFOREGROUND 2>&1 74 | '' 75 | else 76 | '' 77 | HOME=~www-data ${cfg.package}/bin/httpd \ 78 | -f ${config} -DFOREGROUND 2>&1 79 | ''); 80 | enabled = true; 81 | }; 82 | 83 | users.users."www-data" = mkIf cfg.createUserGroup { 84 | description = "Apache HTTPD"; 85 | group = "www-data"; 86 | createHome = false; 87 | home = "/var/empty"; 88 | useDefaultShell = true; 89 | uid = config.ids.uids.www-data; 90 | }; 91 | 92 | users.groups."www-data" = mkIf cfg.createUserGroup { 93 | gid = config.ids.gids.www-data; 94 | }; 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /modules/services/certbot.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.certbot; 13 | 14 | domainOptions = { 15 | options = { 16 | extraDomains = mkOption { 17 | description = "Extra domains to add to the generated certificate."; 18 | type = with types; listOf str; 19 | default = [ ]; 20 | }; 21 | 22 | webroot = mkOption { 23 | description = '' 24 | The path to the webroot where certbot should use for the ACME 25 | challenge. 26 | ''; 27 | type = types.str; 28 | }; 29 | 30 | email = mkOption { 31 | type = types.str; 32 | description = "Contact email address for the CA to be able to reach you."; 33 | }; 34 | 35 | server = mkOption { 36 | type = types.nullOr types.str; 37 | default = null; 38 | description = '' 39 | ACME Directory Resource URI. Defaults to Let's Encrypt's 40 | production endpoint, 41 | , if unset. 42 | ''; 43 | }; 44 | 45 | postScript = mkOption { 46 | description = '' 47 | a shell script to run after certbot. 48 | ''; 49 | type = types.nullOr types.str; 50 | default = null; 51 | }; 52 | 53 | extraOptions = mkOption { 54 | description = '' 55 | Extra command line options passed to certbot upon activation. 56 | ''; 57 | type = types.nullOr types.str; 58 | default = null; 59 | }; 60 | }; 61 | }; 62 | in 63 | { 64 | options = { 65 | services.certbot = { 66 | enable = mkEnableOption "Onable certbot, certificate management tool."; 67 | package = mkOption { 68 | description = "certbot package."; 69 | type = types.package; 70 | default = pkgs.certbot; 71 | }; 72 | 73 | domains = mkOption { 74 | description = "Oomains for which, certbot will fetch certificates."; 75 | type = with types; attrsOf (submodule domainOptions); 76 | default = { }; 77 | }; 78 | 79 | acceptTerms = mkOption { 80 | description = '' 81 | Accept the CA's terms of service. The default provider is Let's Encrypt, 82 | you can find their ToS at . 83 | ''; 84 | type = types.bool; 85 | default = false; 86 | }; 87 | }; 88 | }; 89 | 90 | config = mkIf cfg.enable { 91 | services.crond = { 92 | enable = mkDefault true; 93 | 94 | crontabs.certbot = { 95 | jobs = 96 | let 97 | script = pkgs.writeShellScript "certbot-renew" 98 | '' 99 | ${cfg.package}/bin/certbot renew 100 | ''; 101 | in 102 | [ "0 0 * * * root ${script}" ]; 103 | }; 104 | }; 105 | 106 | assertions = [ 107 | { 108 | assertion = cfg.acceptTerms; 109 | message = '' 110 | You must accept the CA's terms of service before using 111 | the ACME module by setting `services.certbot.acceptTerms` 112 | to `true`. For Let's Encrypt's ToS see https://letsencrypt.org/repository/ 113 | ''; 114 | } 115 | ]; 116 | 117 | system.activation.certbot = nglib.dag.dagEntryAfter 118 | [ "createbaseenv" "users" ] 119 | (concatStringsSep "\n" (mapAttrsToList 120 | (n: v: 121 | pkgs.writeShellScript n '' 122 | ${pkgs.busybox}/bin/mkdir -p ${v.webroot} 123 | ${cfg.package}/bin/certbot certonly \ 124 | --standalone \ 125 | -d ${n} \ 126 | -n \ 127 | ${optionalString (v.server != null) ("--server" + v.server)} \ 128 | --email ${v.email} \ 129 | --agree-tos \ 130 | ${optionalString (v.extraOptions != null) v.extraOptions} \ 131 | ${concatMapStringsSep " " (d: "-d " + d) v.extraDomains} 132 | 133 | ${optionalString (v.postScript != null) v.postScript} 134 | '') 135 | cfg.domains)); 136 | }; 137 | } 138 | -------------------------------------------------------------------------------- /modules/services/crond.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { config, nglib, lib, pkgs, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.crond; 13 | in 14 | { 15 | options.services.crond = { 16 | enable = mkEnableOption "Enable crond, the daemon to execute scheduled commands, specifically cronie."; 17 | package = mkOption { 18 | type = types.package; 19 | description = "The package which contains a cron implementation."; 20 | default = pkgs.cronie; 21 | }; 22 | 23 | crontabs = mkOption { 24 | type = with types; attrsOf (submodule { 25 | options = { 26 | environment = mkOption { 27 | type = attrsOf str; 28 | description = '' 29 | A set of environment variable to set for this specific crontab. 30 | ''; 31 | example = '' 32 | { 33 | MAILTO="root"; 34 | } 35 | ''; 36 | default = { }; 37 | }; 38 | jobs = mkOption { 39 | type = listOf str; 40 | description = '' 41 | A list of job entries, in the usual cron format. 42 | ''; 43 | example = '' 44 | [ 45 | "5 0 * * * www-data rm /var/log/{httpd.access,httpd.error}" 46 | ] 47 | ''; 48 | default = [ ]; 49 | }; 50 | }; 51 | }); 52 | description = '' 53 | Defines cron jobs, allows for the creation of multiple files and entries. 54 | ''; 55 | default = { }; 56 | example = '' 57 | { 58 | "delete-log" = { 59 | environment = { 60 | MAILTO="root"; 61 | }; 62 | jobs = [ 63 | "5 0 * * * www-data rm /var/log/{httpd.access,httpd.error}" 64 | ]; 65 | }; 66 | } 67 | ''; 68 | 69 | apply = x: 70 | let 71 | cronfiles = 72 | (mapAttrsToList 73 | (n: v: pkgs.writeText n 74 | '' 75 | ${concatStringsSep "\n" (mapAttrsToList (n: v: ''"${n}"="${v}"'') v.environment)} 76 | ${concatStringsSep "\n" v.jobs} 77 | '') 78 | x); 79 | in 80 | pkgs.runCommandNoCCLocal "cron.d" { } '' 81 | CRONFILES="${concatStringsSep " " cronfiles}" 82 | mkdir -p $out 83 | for cronfile in $CRONFILES ; do 84 | ln -s "$cronfile" $out/$(basename "$cronfile") 85 | done 86 | ''; 87 | }; 88 | }; 89 | 90 | config = mkIf cfg.enable { 91 | system.activation."crond" = nglib.dag.dagEntryAnywhere 92 | '' 93 | export PATH=${pkgs.busybox}/bin 94 | 95 | mkdir -p /etc /var/run /var/spool/cron /var/cron 96 | ln -s ${cfg.crontabs}/ /etc/cron.d 97 | ''; 98 | 99 | init.services.crond = 100 | { 101 | script = '' 102 | ${cfg.package}/bin/crond -n -x ext,sch,misc 103 | ''; 104 | enabled = true; 105 | }; 106 | }; 107 | } 108 | -------------------------------------------------------------------------------- /modules/services/dovecot.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, nglib, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.dovecot; 13 | 14 | modulesDir = pkgs.symlinkJoin { 15 | name = "dovecot-modules"; 16 | paths = map (pkg: "${cfg.package}/lib/dovecot") 17 | ([ cfg.package ] ++ map (module: module.override { dovecot = cfg.package; }) cfg.modules); 18 | }; 19 | 20 | inherit (config) ids; 21 | in 22 | { 23 | options = { 24 | services.dovecot = { 25 | enable = mkEnableOption "Enable Dovecot."; 26 | 27 | package = mkOption { 28 | description = "Dovecot package."; 29 | type = types.package; 30 | default = pkgs.dovecot; 31 | }; 32 | 33 | user = mkOption { 34 | description = "Dovecot user."; 35 | type = types.str; 36 | default = "dovecot"; 37 | }; 38 | 39 | group = mkOption { 40 | description = "Dovecot group."; 41 | type = types.str; 42 | default = "dovecot"; 43 | }; 44 | 45 | mailUser = mkOption { 46 | description = "Dovecot mail user."; 47 | type = types.nullOr types.str; 48 | default = "vmail"; 49 | }; 50 | 51 | mailGroup = mkOption { 52 | description = "Dovecot mail group."; 53 | type = types.nullOr types.str; 54 | default = "vmail"; 55 | }; 56 | 57 | loginUser = mkOption { 58 | description = "Dovecot user for untrusted logins, should not have access to anything."; 59 | type = types.nullOr types.str; 60 | default = "dovenull"; 61 | }; 62 | 63 | modules = mkOption { 64 | type = types.listOf types.package; 65 | default = [ ]; 66 | example = literalExample "[ pkgs.dovecot_pigeonhole ]"; 67 | description = '' 68 | Symlinks the contents of lib/dovecot of every given package into 69 | the haskell modules directory. This will make the given modules available 70 | if a dovecot package with the module_dir patch applied is being used. 71 | ''; 72 | }; 73 | 74 | config = mkOption { 75 | type = with types; 76 | let 77 | self = attrsOf (nullOr (oneOf [ 78 | str 79 | int 80 | package 81 | bool 82 | (listOf (oneOf [ str int package bool ])) 83 | (attrsOf self) 84 | ])); 85 | in 86 | self // { description = "loop breaker"; }; 87 | description = "Dovecot configuration entries in Nix format."; 88 | default = { }; 89 | apply = x: pkgs.writeText "dovecot.conf" (nglib.generators.toDovecot x); 90 | }; 91 | 92 | extConfig = mkOption { 93 | type = with types; 94 | let 95 | self = attrsOf (nullOr (oneOf [ 96 | str 97 | int 98 | package 99 | bool 100 | (listOf (oneOf [ str int package bool ])) 101 | (attrsOf self) 102 | ])); 103 | in 104 | self // { description = "loop breaker"; }; 105 | description = "Extra config files to generate, if you pass in a config attrset, you can access the generated file via the `config.services.dovecot.extConfig.` attribute."; 106 | default = { }; 107 | apply = x: mapAttrs (n: v: pkgs.writeText n (nglib.generators.toDovecot v)) x; 108 | }; 109 | }; 110 | }; 111 | 112 | config = mkIf cfg.enable 113 | { 114 | users.users."dovecot" = mkIf (cfg.user == "dovecot") { 115 | uid = ids.uids.dovecot; 116 | description = "Dovecot user."; 117 | group = "dovecot"; 118 | }; 119 | users.groups."dovecot" = mkIf (cfg.group == "dovecot") { 120 | gid = ids.gids.dovecot; 121 | }; 122 | users.users."vmail" = mkIf (cfg.mailUser == "vmail") { 123 | uid = ids.uids.vmail; 124 | description = "vmail user."; 125 | group = "vmail"; 126 | }; 127 | users.groups."vmail" = mkIf (cfg.mailGroup == "vmail") { 128 | gid = ids.gids.vmail; 129 | }; 130 | users.users."dovenull" = mkIf (cfg.loginUser == "dovenull") { 131 | uid = ids.uids.dovenull; 132 | description = "Dovecot untrusted login user."; 133 | group = "dovenull"; 134 | }; 135 | users.groups."dovenull" = mkIf (cfg.loginUser == "dovenull") { 136 | gid = ids.gids.dovenull; 137 | }; 138 | 139 | services.dovecot = { 140 | config = { 141 | default_login_user = mkIf (cfg.loginUser != null) cfg.loginUser; 142 | default_internal_user = mkIf (cfg.user != null) cfg.user; 143 | default_internal_group = mkIf (cfg.group != null) cfg.group; 144 | 145 | auth_mechanisms = mkDefault "plain"; 146 | 147 | namespace."inbox" = { 148 | inbox = true; 149 | 150 | mailbox."Drafts" = { 151 | special_use = "\\Drafts"; 152 | }; 153 | 154 | mailbox."Junk" = { 155 | special_use = "\\Junk"; 156 | }; 157 | 158 | mailbox."Trash" = { 159 | special_use = "\\Trash"; 160 | }; 161 | 162 | mailbox."Sent" = { 163 | special_use = "\\Sent"; 164 | }; 165 | 166 | mailbox."Sent Messages" = { 167 | special_use = "\\Sent"; 168 | }; 169 | }; 170 | }; 171 | }; 172 | 173 | init.services.dovecot = 174 | { 175 | ensureSomething.link."modules" = mkDefault { 176 | src = modulesDir; 177 | dst = "/etc/dovecot/modules"; 178 | persistent = false; 179 | }; 180 | 181 | ensureSomething.link."config" = mkDefault { 182 | src = cfg.config; 183 | dst = "/etc/dovecot/dovecot.conf"; 184 | persistent = false; 185 | }; 186 | 187 | script = pkgs.writeShellScript "dovecot-run" 188 | '' 189 | echo ${cfg.package}/sbin/dovecot -F 190 | ${cfg.package}/sbin/dovecot -F 191 | ''; 192 | enabled = true; 193 | }; 194 | }; 195 | } 196 | -------------------------------------------------------------------------------- /modules/services/getty.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.getty; 13 | in 14 | { 15 | options.services.getty = mkOption { 16 | description = "All of the agettys"; 17 | type = types.attrsOf (types.submodule { 18 | options = { 19 | baudRate = mkOption { 20 | description = "TTY baud rate"; 21 | type = types.int; 22 | }; 23 | termName = mkOption { 24 | description = "TTY terminal name"; 25 | type = types.str; 26 | default = "vt100"; 27 | }; 28 | assume8BitTty = mkOption { 29 | description = "Whether to assume the tty is 8-bit"; 30 | type = types.bool; 31 | default = true; 32 | }; 33 | # TODO Local line -L 34 | pkg = mkOption { 35 | description = "getty package"; 36 | type = types.path; 37 | default = "${pkgs.utillinuxMinimal}/bin/agetty"; 38 | }; 39 | }; 40 | }); 41 | default = { }; 42 | }; 43 | config.init.services = mapAttrs' 44 | (name: getty: nameValuePair "getty-${name}" 45 | { 46 | script = with getty; 47 | pkgs.writeShellScript "getty-${name}-run" 48 | '' 49 | exec setsid ${pkg} ${optionalString assume8BitTty "-8"} "${name}" "${toString baudRate}" "${termName}" 50 | ''; 51 | enabled = true; 52 | }) 53 | cfg; 54 | } 55 | -------------------------------------------------------------------------------- /modules/services/gitea.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, config, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.gitea; 13 | ids = config.ids; 14 | 15 | defaultUser = "gitea"; 16 | 17 | giteaSecrets = { 18 | options = { 19 | secretKeyFile = mkOption { 20 | description = '' 21 | Path to a file containing Gitea's secret key, on one line. 22 | If non-null, the contents of this file will 23 | substituted into the generated configuration file in-place of 24 | #secretKey#. 25 | ''; 26 | type = with types; nullOr path; 27 | default = null; 28 | }; 29 | internalTokenFile = mkOption { 30 | description = '' 31 | Path to a file containing Gitea's internal token, on one line. 32 | If non-null, the contents of this file will 33 | substituted into the generated configuration file in-place of 34 | #internalToken#. 35 | ''; 36 | type = with types; nullOr path; 37 | default = null; 38 | }; 39 | jwtSecretFile = mkOption { 40 | description = '' 41 | Path to a file containing Gitea's JWT secret, on one line. 42 | If non-null, the contents of this file 43 | will substituted into the generated configuration file in-place 44 | of #jwtSecret#. 45 | ''; 46 | type = with types; nullOr path; 47 | default = null; 48 | }; 49 | lfsJwtSecretFile = mkOption { 50 | description = '' 51 | Path to a file containing Gitea's LFS JWT secret, on one line. 52 | If non-null, the contents of this file will 53 | substituted into the generated configuration file in-place of 54 | #lfsJwtSecret#. 55 | ''; 56 | type = with types; nullOr path; 57 | default = null; 58 | }; 59 | 60 | databaseUserFile = mkOption { 61 | description = '' 62 | Path to a file containing user with which Gitea should connect 63 | to it's database, on one line. If non-null, 64 | the contents of this file will substituted into the generated 65 | configuration file in-place of #databaseUser#. 66 | ''; 67 | type = with types; nullOr path; 68 | default = null; 69 | }; 70 | databasePasswordFile = mkOption { 71 | description = '' 72 | Path to a file containing password with which Gitea should 73 | connect to it's database, on one line. If 74 | on-null, the contents of this file will 75 | substituted into the generated configuration file in-place 76 | of #databasePassword#. 77 | ''; 78 | type = with types; nullOr path; 79 | default = null; 80 | }; 81 | databaseHostFile = mkOption { 82 | description = '' 83 | Path to a file containing database host to which Gitea should 84 | connect, on one line. If non-null, the 85 | contents of this file will substituted into the generated 86 | configuration file in-place of #databaseHost#. 87 | ''; 88 | type = with types; nullOr path; 89 | default = null; 90 | }; 91 | }; 92 | }; 93 | in 94 | { 95 | options.services.gitea = { 96 | enable = mkEnableOption "Enable Gitea service."; 97 | 98 | package = mkOption { 99 | description = "Gitea package."; 100 | type = types.package; 101 | default = pkgs.gitea; 102 | }; 103 | 104 | secrets = mkOption { 105 | description = "Gitea secrets."; 106 | type = types.submodule giteaSecrets; 107 | default = { }; 108 | }; 109 | 110 | configuration = mkOption { 111 | description = '' 112 | Gitea configuration. APP_NAME, 113 | RUN_MODE, and RUN_USER 114 | are specified separately, because they are not under any section, 115 | therefore the Gitea configuration file isn't a real INI file. 116 | ''; 117 | type = types.attrs; 118 | example = '' 119 | { 120 | repository = { ROOT = /data/gitea/git/repositories; }; 121 | repository.local = { LOCAL_COPY_PATH = /data/gitea/tmp/local-repo; }; 122 | } 123 | ''; 124 | }; 125 | 126 | appName = mkOption { 127 | description = '' 128 | Gitea's app name, displayed on the front page. 129 | As to why this is explicitly set here, see 130 | . 131 | ''; 132 | type = types.str; 133 | default = "Gitea"; 134 | }; 135 | runMode = mkOption { 136 | description = '' 137 | Gitea's run mode. 138 | As to why this is explicitly set here, see 139 | . 140 | ''; 141 | type = types.str; 142 | default = "prod"; 143 | }; 144 | user = mkOption { 145 | description = '' 146 | Gitea's user. Under which the Gitea process runs. 147 | ''; 148 | type = types.str; 149 | default = defaultUser; 150 | }; 151 | 152 | runConfig = mkOption { 153 | description = '' 154 | Path to Gitea's runtime generated configuration, with secrets. 155 | ''; 156 | type = types.path; 157 | default = "/var/run/gitea/app.ini"; 158 | }; 159 | # add explicit path settings and ensure them, also add to config but only as defaults 160 | }; 161 | 162 | config = { 163 | init.services.gitea = mkIf cfg.enable { 164 | ensureSomething.create."0-server.APP_DATA_PATH" = { 165 | type = "directory"; 166 | mode = "755"; 167 | owner = "gitea:nogroup"; 168 | persistent = true; 169 | dst = cfg.configuration."server"."APP_DATA_PATH"; 170 | }; 171 | 172 | ensureSomething.create."runConfig" = { 173 | type = "file"; 174 | mode = "400"; 175 | owner = "gitea:nogroup"; 176 | persistent = false; 177 | dst = cfg.runConfig; 178 | }; 179 | 180 | script = pkgs.writeShellScript "gitea-run" 181 | ( 182 | let 183 | appIni = pkgs.writeText "app.ini" 184 | '' 185 | APP_NAME = ${cfg.appName} 186 | RUN_MODE = ${cfg.runMode} 187 | RUN_USER = ${cfg.user} 188 | 189 | ${generators.toINI {} cfg.configuration} 190 | ''; 191 | inherit (cfg.secrets) secretKeyFile internalTokenFile jwtSecretFile lfsJwtSecretFile databaseUserFile databasePasswordFile databaseHostFile; 192 | 193 | subsSecret = source: key: 194 | optionalString (source != null) 195 | '' 196 | if [[ -f '${source}' ]] ; then 197 | SECRET="$(head -n1 ${source})" 198 | sed -i "s,#${key}#,$SECRET,g" ${cfg.runConfig} 199 | echo 'Substituted contents of `${source}` in place of `#${key}#`' 200 | fi 201 | ''; 202 | in 203 | '' 204 | export PATH=${pkgs.busybox}/bin:${pkgs.bash}/bin 205 | 206 | cp ${appIni} ${cfg.runConfig} 207 | 208 | ${subsSecret secretKeyFile "secretKey"} 209 | ${subsSecret internalTokenFile "internalToken"} 210 | ${subsSecret jwtSecretFile "jwtSecret"} 211 | ${subsSecret lfsJwtSecretFile "lfsJwtSecret"} 212 | ${subsSecret databaseUserFile "databaseUser"} 213 | ${subsSecret databasePasswordFile "databasePassword"} 214 | ${subsSecret databaseHostFile "databaseHost"} 215 | 216 | export HOME=${cfg.configuration.repository.ROOT} 217 | chpst -u ${cfg.user}:nogroup ${cfg.package}/bin/gitea -c ${cfg.runConfig} 218 | '' 219 | ); 220 | 221 | enabled = true; 222 | }; 223 | 224 | users.users."gitea" = mkIf (cfg.enable && cfg.user == defaultUser) { 225 | uid = ids.uids.gitea; 226 | description = "Gitea user"; 227 | }; 228 | }; 229 | } 230 | -------------------------------------------------------------------------------- /modules/services/home-assistant.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, nglib, ... }: 10 | with nglib; with lib; 11 | let 12 | cfg = config.services.home-assistant; 13 | format = pkgs.formats.yaml {}; 14 | 15 | configDir = pkgs.runCommandNoCC "home-assistant-config-dir" {} 16 | '' 17 | mkdir -p $out 18 | ln -s ${format.generate "configuration.yaml" cfg.config} $out/configuration.yaml 19 | ''; 20 | in 21 | { 22 | options.services.home-assistant = { 23 | enable = mkEnableOption "Enable Home Assistant"; 24 | 25 | package = mkOption { 26 | type = with types; package; 27 | default = pkgs.home-assistant; 28 | description = '' 29 | Which home-assistant package to use. Adding components is a shorthand for adding python packages. 30 | ''; 31 | }; 32 | 33 | customComponents = mkOption { 34 | type = with types; attrsOf (oneOf [ package str ]); 35 | default = {}; 36 | description = '' 37 | Extra components to be installed into /run/home-assistant/custom_components. 38 | ''; 39 | }; 40 | 41 | config = mkOption { 42 | type = format.type; 43 | default = {}; 44 | description = '' 45 | Home Assistant configuration, https://www.home-assistant.io/docs/configuration/. 46 | ''; 47 | }; 48 | 49 | user = mkOption { 50 | description = "Home Assistant user."; 51 | type = types.str; 52 | default = "home-assistant"; 53 | }; 54 | 55 | group = mkOption { 56 | description = "Home Assistant group."; 57 | type = types.str; 58 | default = "home-assistant"; 59 | }; 60 | 61 | envsubst = mkEnableOption "Run envsubst on the configuration file."; 62 | }; 63 | 64 | config = mkIf cfg.enable { 65 | services.home-assistant.config = mkDefaultRec 66 | { 67 | http.server_port = "8123"; 68 | }; 69 | 70 | init.services.home-assistant = { 71 | script = pkgs.writeShellScript "home-assistant-run" 72 | '' 73 | mkdir -p /var/home-assistant/ 74 | cp '${configDir}'/* /var/home-assistant/ 75 | ${optionalString cfg.envsubst 76 | '' 77 | rm /var/home-assistant/configuration.yaml 78 | ${pkgs.envsubst}/bin/envsubst \ 79 | < '${configDir}/configuration.yaml' \ 80 | > /var/home-assistant/configuration.yaml 81 | '' 82 | } 83 | 84 | ${if cfg.customComponents != {} then "mkdir /var/home-assistant/custom_components" else ""} 85 | ${concatStringsSep "\n" (mapAttrsToList (n: v: "ln -sf ${v} /var/home-assistant/custom_components/${n}") cfg.customComponents)} 86 | 87 | chown -R ${cfg.user}:${cfg.group} /var/home-assistant/ 88 | chmod -R u=rwX,g=r-X,o= /var/home-assistant/ 89 | 90 | chpst -u ${cfg.user}:${cfg.group} -b home-assistant ${cfg.package}/bin/hass --runner --config /var/home-assistant 91 | ''; 92 | enabled = true; 93 | }; 94 | 95 | users.users.${cfg.user} = mkDefaultRec { 96 | description = "Home Assistant"; 97 | group = cfg.group; 98 | createHome = false; 99 | home = "/var/empty"; 100 | useDefaultShell = true; 101 | uid = config.ids.uids.home-assistant; 102 | }; 103 | 104 | users.groups.${cfg.group} = mkDefaultRec { 105 | gid = config.ids.gids.home-assistant; 106 | }; 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /modules/services/jmusicbot.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.jmusicbot; 13 | in 14 | { 15 | options.services.jmusicbot = { 16 | enable = mkEnableOption "Enable JMusicBot"; 17 | 18 | package = mkOption { 19 | description = "JMusicBot package to use."; 20 | default = pkgs.jmusicbot; 21 | type = types.package; 22 | }; 23 | 24 | config = mkOption { 25 | description = '' 26 | JMusicBot configuration file in Nix form. https://github.com/jagrosh/MusicBot/wiki/Example-Config 27 | This configuration file will be ran through envsubst, therefore "''${ENV_VAR}" works as you'd expect. 28 | ''; 29 | example = literalExample '' 30 | { 31 | token = "BOT_TOKEN"; 32 | owner = 1254789614; 33 | songinstatus = false; 34 | 35 | aliases = { 36 | settings = [ "status" ]; 37 | }; 38 | } 39 | ''; 40 | type = with types; attrsOf (oneOf [ str int bool (attrsOf (listOf str)) ]); 41 | apply = x: 42 | pkgs.writeText "jmusicbot-config.txt" 43 | (concatMapStringsSep "\n" 44 | ( 45 | { name, value }: 46 | if isString value then 47 | "${name} = \"${value}\"" 48 | else if isInt value then 49 | "${name} = ${toString value}" 50 | else if isBool value then 51 | if value then 52 | "${name} = true" 53 | else 54 | "${name} = false" 55 | else if isAttrs value then 56 | "${name} {" 57 | + 58 | concatMapStringsSep "\n" ( 59 | { name, value }: 60 | "${name} = [ ${concatStringsSep ", " value} ]" 61 | ) 62 | + 63 | "}" 64 | else 65 | throw "Type error" 66 | ) 67 | (mapAttrsToList nameValuePair x)); 68 | }; 69 | 70 | user = mkOption { 71 | description = "User to run JMusicBot under."; 72 | default = "jmusicbot"; 73 | type = types.str; 74 | }; 75 | 76 | group = mkOption { 77 | description = "Group to run JMusicBot under."; 78 | default = "jmusicbot"; 79 | type = types.str; 80 | }; 81 | }; 82 | 83 | config = mkIf cfg.enable { 84 | users.users.${cfg.user} = mapAttrs (_: mkDefault) { 85 | description = "JMusicBot"; 86 | group = cfg.group; 87 | home = "/var/empty"; 88 | useDefaultShell = true; 89 | createHome = false; 90 | uid = config.ids.uids.jmusicbot; 91 | }; 92 | 93 | users.groups.${cfg.group} = { 94 | gid = mkDefault config.ids.gids.jmusicbot; 95 | }; 96 | 97 | init.services.jmusicbot = 98 | { 99 | script = pkgs.writeShellScript "jmusicbot-run" 100 | '' 101 | mkdir -p /run/cfg/jmusicbot 102 | ${pkgs.envsubst}/bin/envsubst < ${cfg.config} > /run/cfg/jmusicbot/config.txt 103 | 104 | cd /run/cfg/jmusicbot 105 | # chpst -u ${cfg.user}:${cfg.group} 106 | ${cfg.package}/bin/JMusicBot 107 | ''; 108 | enabled = true; 109 | }; 110 | }; 111 | } 112 | -------------------------------------------------------------------------------- /modules/services/minecraft.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.minecraft; 13 | format = pkgs.formats.json {}; 14 | 15 | jqMeld = pkgs.writeText "meld.jq" 16 | '' 17 | # Recursively meld a and b, 18 | # concatenating arrays and 19 | # favoring b when there is a conflict 20 | def meld(a; b): 21 | a as $a | b as $b 22 | | if ($a|type) == "object" and ($b|type) == "object" 23 | then reduce ([$a,$b]|add|keys_unsorted[]) as $k ({}; 24 | .[$k] = meld( $a[$k]; $b[$k]) ) 25 | elif ($a|type) == "array" and ($b|type) == "array" 26 | then $a+$b 27 | elif $b == null then $a 28 | else $b 29 | end; 30 | ''; 31 | forgeConfigured = pkgs.runCommandNoCC "forge-configured" {} 32 | '' 33 | set -xe 34 | 35 | mkdir -p $out 36 | cd $out 37 | ${pkgs.unzip}/bin/unzip ${cfg.forgeZipFile} 38 | 39 | _server_folder="$out/"*"/" 40 | mv $_server_folder/* . 41 | rm -r $_server_folder 42 | 43 | ${pkgs.yq-go}/bin/yq eval-all '. as $item ireduce ({}; . *+ $item)' server-setup-config.yaml ${cfg.forgeConfigOverrides} > server-setup-config-new.yaml 44 | mv server-setup-config-new.yaml server-setup-config.yaml 45 | ''; 46 | 47 | forgeFetched = pkgs.stdenv.mkDerivation { 48 | name = "forge"; 49 | src = forgeConfigured; 50 | 51 | nativeBuildInputs = with pkgs; [ 52 | # fakeJava 53 | cfg.javaPackage 54 | curl 55 | cacert 56 | ]; 57 | 58 | buildPhase = '' 59 | sh startserver.sh 60 | ''; 61 | 62 | installPhase = '' 63 | mkdir -p $out 64 | cp -r * $out 65 | ''; 66 | 67 | outputHashMode = "recursive"; 68 | outputHashAlgo = "sha256"; 69 | outputHash = cfg.forgeFetchedHash; 70 | }; 71 | in 72 | { 73 | options.services.minecraft = { 74 | enable = mkEnableOption "Enable Minecraft server service."; 75 | 76 | forgeZipFile = mkOption { 77 | type = with types; nullOr path; 78 | description = '' 79 | Path to zip file containing a Forge formatted MC server. 80 | ''; 81 | default = null; 82 | }; 83 | 84 | forgeConfigOverrides = mkOption { 85 | type = with types; format.type; 86 | description = '' 87 | Config overrides to apply to Forge config file. 88 | ''; 89 | default = {}; 90 | apply = x: pkgs.writeText "forge-config-overrides.json" (builtins.toJSON x); 91 | }; 92 | 93 | forgeFetchedHash = mkOption { 94 | type = with types; str; 95 | description = '' 96 | The output hash of running `serverstart.sh`. 97 | ''; 98 | }; 99 | 100 | javaPackage = mkOption { 101 | type = with types; package; 102 | description = '' 103 | Which Java path should be used. 104 | ''; 105 | default = pkgs.jdk11; 106 | }; 107 | 108 | overlayfsPackage = mkOption { 109 | type = with types; package; 110 | description = '' 111 | Which Java path should be used. 112 | ''; 113 | default = pkgs.fuse-overlayfs; 114 | }; 115 | 116 | eulaAccept = mkOption { 117 | type = with types; bool; 118 | description = '' 119 | By changing the setting below to true you are indicating your agreement to Mojang's EULA (https://account.mojang.com/documents/minecraft_eula). 120 | ''; 121 | default = false; 122 | }; 123 | }; 124 | 125 | config = mkIf cfg.enable { 126 | init.services.minecraft = 127 | { 128 | script = pkgs.writeShellScript "minecraft-run" 129 | '' 130 | set -xe 131 | 132 | mkdir -p /run/cfg/minecraft/{upperdir,workdir} 133 | ${cfg.overlayfsPackage}/bin/fuse-overlayfs -o lowerdir=${forgeFetched},upperdir=/run/cfg/minecraft/upperdir,workdir=/run/cfg/minecraft/workdir /run/cfg/minecraft 134 | 135 | cd /run/cfg/minecraft 136 | echo "eula=true" > ./eula.txt 137 | export PATH=$PATH:${cfg.javaPackage}/bin 138 | sh ./startserver.sh 139 | ''; 140 | enabled = true; 141 | }; 142 | 143 | assertions = [ 144 | { assertion = cfg.eulaAccept; 145 | message = "You must accept the EULA"; 146 | } 147 | ]; 148 | }; 149 | } 150 | -------------------------------------------------------------------------------- /modules/services/mosquitto.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, nglib, ... }: 10 | with nglib; with lib; 11 | let 12 | cfg = config.services.mosquitto; 13 | 14 | format = 15 | { type = with types; 16 | let self = attrsOf (oneOf [ str path bool int (listOf (oneOf [ str path bool int self ])) ]); 17 | in self // { description = "attrs of str, path, bool, int or attrs of self"; }; 18 | generate = config: 19 | pkgs.writeTextFile 20 | { name = "mosquitto.conf"; 21 | text = let 22 | self = config: 23 | mapAttrsToList 24 | (n: v: 25 | if isString v || isInt v then 26 | "${n} ${toString v}\n" 27 | else if isBool v then 28 | "${n} ${if v then "true" else "false"}\n" 29 | else if isList v then 30 | if length v != 2 then 31 | throw "Invalid subtree list length of ${length v}" 32 | else if (isString (elemAt v 0) || isInt (elemAt v 0)) && isAttrs (elemAt v 1) then 33 | "${n} ${toString (elemAt v 0)}\n${concatStringsSep " " (self (elemAt v 1))}" 34 | else if (isBool (elemAt v 0)) && isAttrs (elemAt v 1) then 35 | "${n} ${if elemAt v 0 then "true" else "false"}\n${concatStringsSep " " (self (elemAt v 1))}" 36 | else 37 | throw "Invalid subtree content" 38 | else 39 | throw "unreachable" 40 | ) 41 | config; 42 | in self config; 43 | }; 44 | }; 45 | in 46 | { 47 | options.services.mosquitto = { 48 | enable = mkEnableOption "Enable Mosquitto MQTT broker."; 49 | 50 | package = mkOption { 51 | type = with types; package; 52 | default = pkgs.mosquitto; 53 | description = '' 54 | Which mosquitto package to use. 55 | ''; 56 | }; 57 | 58 | config = mkOption { 59 | type = format.type; 60 | default = {}; 61 | description = '' 62 | Mosquitto configuration, https://mosquitto.org/man/mosquitto-conf-5.html. 63 | ''; 64 | }; 65 | 66 | user = mkOption { 67 | description = "mosquitto user."; 68 | type = types.str; 69 | default = "mosquitto"; 70 | }; 71 | 72 | group = mkOption { 73 | description = "mosquitto group."; 74 | type = types.str; 75 | default = "mosquitto"; 76 | }; 77 | 78 | envsubst = mkEnableOption "Run envsubst on the configuration file."; 79 | }; 80 | 81 | config = mkIf cfg.enable { 82 | services.mosquitto.config = mkDefaultRec 83 | { 84 | persistence = true; 85 | persistence_location = "/var/mosquitto"; 86 | listener = 87 | ["1883 0.0.0.0" 88 | ({ allow_anonymous = true; 89 | }) 90 | ]; 91 | }; 92 | 93 | init.services.mosquitto = { 94 | script = pkgs.writeShellScript "mosquitto-run" 95 | '' 96 | mkdir -p /var/mosquitto/ /run/mosquitto 97 | cp ${format.generate cfg.config} /run/mosquitto/configuration.yaml 98 | ${optionalString cfg.envsubst 99 | '' 100 | rm /run/mosquitto/configuration.yaml 101 | ${pkgs.envsubst}/bin/envsubst \ 102 | < '${format.generate cfg.config}' \ 103 | > /run/mosquitto/configuration.yaml 104 | '' 105 | } 106 | 107 | chown -R ${cfg.user}:${cfg.group} /var/mosquitto/ 108 | chmod -R u=rwX,g=r-X,o= /var/mosquitto/ 109 | 110 | chpst -u ${cfg.user}:${cfg.group} -b mosquitto ${cfg.package}/bin/mosquitto -c /run/mosquitto/configuration.yaml 111 | ''; 112 | enabled = true; 113 | }; 114 | 115 | users.users.${cfg.user} = mkDefaultRec { 116 | description = "mosquitto"; 117 | group = cfg.group; 118 | createHome = false; 119 | home = "/var/empty"; 120 | useDefaultShell = true; 121 | uid = config.ids.uids.mosquitto; 122 | }; 123 | 124 | users.groups.${cfg.group} = mkDefaultRec { 125 | gid = config.ids.gids.mosquitto; 126 | }; 127 | }; 128 | } 129 | -------------------------------------------------------------------------------- /modules/services/mysql.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | # 9 | # This file incorporates work sublicensed from the MIT License to 10 | # Mozilla Public License, v. 2.0, for which the following copyright applies: 11 | # Copyright (c) 2003-2021 Eelco Dolstra and the Nixpkgs/NixOS contributors 12 | 13 | { pkgs, lib, config, ... }: 14 | with lib; 15 | let 16 | cfg = config.services.mysql; 17 | 18 | isMariaDB = lib.getName cfg.package == lib.getName pkgs.mariadb; 19 | superUser = if isMariaDB then cfg.user else "root"; 20 | 21 | mysqldOptions = 22 | "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}"; 23 | 24 | configFile = pkgs.writeText "my.cnf" ( 25 | generators.toINI { listsAsDuplicateKeys = true; } cfg.config 26 | ); 27 | in 28 | { 29 | options.services.mysql = 30 | { 31 | enable = mkEnableOption "MySQL Server"; 32 | 33 | package = mkOption { 34 | type = types.package; 35 | example = literalExample "pkgs.mariadb"; 36 | description = '' 37 | MySQL package to use. You can also use MariaDB and this module will re-adjust. 38 | ''; 39 | default = pkgs.mariadb; 40 | }; 41 | 42 | port = mkOption { 43 | type = types.int; 44 | default = 3306; 45 | description = '' 46 | The port on which MariaDB listens. 47 | ''; 48 | apply = toString; 49 | }; 50 | 51 | bind = mkOption { 52 | type = types.nullOr types.str; 53 | default = null; 54 | example = literalExample "127.0.0.1"; 55 | description = '' 56 | Address to bind to. 57 | ''; 58 | }; 59 | 60 | user = mkOption { 61 | type = types.str; 62 | default = "mysql"; 63 | description = "User account under which MySQL runs."; 64 | }; 65 | 66 | group = mkOption { 67 | type = types.str; 68 | default = "mysql"; 69 | description = "Group under which MySQL runs."; 70 | }; 71 | 72 | dataDir = mkOption { 73 | type = types.path; 74 | default = "/var/lib/mysql"; 75 | description = "Location where MySQL stores its table files."; 76 | }; 77 | 78 | config = mkOption { 79 | type = with types; attrsOf (attrsOf (oneOf [ bool int str (listOf str) ])); 80 | default = { }; 81 | example = literalExample 82 | '' 83 | { 84 | mysqld = { 85 | key_buffer_size = "6G"; 86 | table_cache = 1600; 87 | log-error = "/var/log/mysql_err.log"; 88 | plugin-load-add = [ "server_audit" "ed25519=auth_ed25519" ]; 89 | }; 90 | mysqldump = { 91 | quick = true; 92 | max_allowed_packet = "16M"; 93 | }; 94 | } 95 | ''; 96 | }; 97 | 98 | initialScript = mkOption { 99 | type = with types; nullOr (oneOf [ package str ]); 100 | default = null; 101 | description = '' 102 | A file containing SQL statements to execute on first startup. 103 | ''; 104 | }; 105 | 106 | ensureDatabases = mkOption { 107 | type = types.listOf types.str; 108 | default = [ ]; 109 | description = '' 110 | Ensures that the specified databases exist. 111 | This option will never delete existing databases, especially not when the value of this 112 | option is changed. This means that databases created once through this option or 113 | otherwise have to be removed manually. 114 | ''; 115 | example = [ 116 | "gitea" 117 | "nextcloud" 118 | ]; 119 | }; 120 | 121 | ensureUsers = mkOption { 122 | type = types.listOf (types.submodule { 123 | options = { 124 | name = mkOption { 125 | type = types.str; 126 | description = '' 127 | Name of the user to ensure. 128 | ''; 129 | }; 130 | ensurePermissions = mkOption { 131 | type = types.attrsOf types.str; 132 | default = { }; 133 | description = '' 134 | Permissions to ensure for the user, specified as an attribute set. 135 | The attribute names specify the database and tables to grant the permissions for. 136 | The attribute values specify the permissions to grant. You may specify one or 137 | multiple comma-separated SQL privileges here. 138 | For more information on how to specify the target 139 | and on which privileges exist, see the 140 | GRANT syntax. 141 | The attributes are used as GRANT ''${attrName} ON ''${attrValue}. 142 | ''; 143 | example = literalExample '' 144 | { 145 | "database.*" = "ALL PRIVILEGES"; 146 | "*.*" = "SELECT, LOCK TABLES"; 147 | } 148 | ''; 149 | }; 150 | }; 151 | }); 152 | default = [ ]; 153 | description = '' 154 | Ensures that the specified users exist and have at least the ensured permissions. 155 | The PostgreSQL users will be identified using peer authentication. This authenticates the Unix user with the 156 | same name only, and that without the need for a password. 157 | This option will never delete existing users or remove permissions, especially not when the value of this 158 | option is changed. This means that users created and permissions assigned once through this option or 159 | otherwise have to be removed manually. 160 | ''; 161 | example = literalExample '' 162 | [ 163 | { 164 | name = "nextcloud"; 165 | ensurePermissions = { 166 | "database.*" = "ALL PRIVILEGES"; 167 | }; 168 | } 169 | { 170 | name = "superuser"; 171 | ensurePermissions = { 172 | "*.*" = "SELECT, LOCK TABLES"; 173 | }; 174 | } 175 | ] 176 | ''; 177 | }; 178 | }; 179 | 180 | config = mkIf cfg.enable 181 | { 182 | services.mysql.config.mysqld = { 183 | datadir = cfg.dataDir; 184 | bind-address = mkIf (cfg.bind != null) cfg.bind; 185 | port = cfg.port; 186 | }; 187 | 188 | users.users.mysql = mapAttrs (_: mkDefault) 189 | { 190 | uid = config.ids.uids.mysql; 191 | group = "mysql"; 192 | description = "MySQL server user"; 193 | createHome = false; 194 | home = "${cfg.dataDir}"; 195 | useDefaultShell = true; 196 | }; 197 | 198 | users.groups.mysql.gid = config.ids.gids.mysql; 199 | 200 | init.services.mysql = { 201 | ensureSomething.create."dataDir" = { 202 | type = "directory"; 203 | mode = "750"; 204 | owner = "${cfg.user}:${cfg.group}"; 205 | persistent = true; 206 | dst = cfg.dataDir; 207 | }; 208 | 209 | ensureSomething.create."runSocket" = { 210 | type = "directory"; 211 | mode = "755"; 212 | owner = "${cfg.user}:${cfg.group}"; 213 | persistent = false; 214 | dst = "/run/mysqld/"; 215 | }; 216 | 217 | script = pkgs.writeShellScript "mysql" '' 218 | if [[ ! -e ${cfg.dataDir}/mysql ]] ; then 219 | test -e ${cfg.package}/bin/mysql_install_db && ${cfg.package}/bin/mysql_install_db --defaults-file=${configFile} ${mysqldOptions} 220 | test -e ${cfg.package}/bin/mysqld && ${cfg.package}/bin/mysqld --defaults-file=${configFile} ${mysqldOptions} --initialize-insecure 221 | 222 | touch ${cfg.dataDir}/.first_startup 223 | fi 224 | 225 | chpst -u ${cfg.user}:${cfg.group} ${cfg.package}/bin/mysqld --defaults-file=${configFile} ${mysqldOptions} & 226 | mysql=$! 227 | 228 | while ! [[ -e /run/mysqld/mysqld.sock ]] ; do 229 | if ! kill -0 "$mysql"; then exit 1; fi 230 | sleep 0.1 231 | done 232 | 233 | if [[ -e ${cfg.dataDir}/.first_startup ]] ; then 234 | # While MariaDB comes with a 'mysql' super user account since 10.4.x, MySQL does not 235 | # Since we don't want to run this service as 'root' we need to ensure the account exists on first run 236 | ( echo "CREATE USER IF NOT EXISTS '${cfg.user}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};" 237 | echo "GRANT ALL PRIVILEGES ON *.* TO '${cfg.user}'@'localhost' WITH GRANT OPTION;" 238 | ) | ${cfg.package}/bin/mysql -u ${superUser} -N 239 | 240 | ${optionalString (cfg.initialScript != null) 241 | '' 242 | # Execute initial script 243 | # using toString to avoid copying the file to nix store if given as path instead of string, 244 | # as it might contain credentials 245 | cat ${toString cfg.initialScript} | ${cfg.package}/bin/mysql -u ${superUser} -N 246 | ''} 247 | 248 | rm ${cfg.dataDir}/.first_startup 249 | fi 250 | 251 | ${optionalString (cfg.ensureDatabases != []) '' 252 | ( 253 | ${concatMapStrings (database: '' 254 | echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;" 255 | '') cfg.ensureDatabases} 256 | ) | ${cfg.package}/bin/mysql -N 257 | ''} 258 | ${concatMapStrings (user: 259 | '' 260 | ( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};" 261 | ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' 262 | echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" 263 | '') user.ensurePermissions)} 264 | ) | ${cfg.package}/bin/mysql -N 265 | '') cfg.ensureUsers} 266 | 267 | wait $mysql 268 | ''; 269 | 270 | enabled = true; 271 | }; 272 | }; 273 | } 274 | -------------------------------------------------------------------------------- /modules/services/nginx.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, nglib, ... }: 10 | with nglib; with lib; 11 | let 12 | cfg = config.services.nginx; 13 | runtimeConfig = "/run/cfg/nginx.cfg"; 14 | 15 | inherit (nglib.generators) toNginx; 16 | in 17 | { 18 | options = { 19 | services.nginx = { 20 | enable = mkEnableOption "Enable Nginx http server."; 21 | package = mkOption { 22 | description = "Nginx package."; 23 | type = types.package; 24 | default = pkgs.nginx; 25 | }; 26 | user = mkOption { 27 | description = "Nginx user."; 28 | type = types.str; 29 | default = "nginx"; 30 | }; 31 | group = mkOption { 32 | description = "Nginx group."; 33 | type = types.str; 34 | default = "nginx"; 35 | }; 36 | envsubst = mkEnableOption "Run envsubst on the configuration file."; 37 | configuration = mkOption { 38 | description = "Nginx configuration"; 39 | type = with types; 40 | let 41 | self = 42 | oneOf [ 43 | (attrsOf (oneOf [ 44 | str 45 | int 46 | (listOf (oneOf [ str int (listOf (oneOf [ str int ])) ])) 47 | (attrsOf self) 48 | ])) 49 | (listOf (oneOf [ str self ])) 50 | ]; 51 | in 52 | self // { description = "loop breaker"; }; 53 | }; 54 | }; 55 | }; 56 | 57 | config = mkIf cfg.enable 58 | { 59 | init.services.nginx = 60 | let 61 | config = pkgs.writeText "nginx.cfg" (toNginx cfg.configuration); 62 | in 63 | { 64 | ensureSomething.create."cache" = { 65 | type = "directory"; 66 | mode = "750"; 67 | owner = "${cfg.user}:${cfg.group}"; 68 | dst = "/var/cache/nginx/"; 69 | persistent = false; 70 | }; 71 | script = pkgs.writeShellScript "nginx-run" 72 | (if cfg.envsubst then 73 | '' 74 | export PATH=${pkgs.envsubst}/bin:$PATH 75 | 76 | mkdir -p /run/cfg 77 | install -o nginx -g nginx -m 0440 /dev/null ${runtimeConfig} 78 | envsubst < ${config} > ${runtimeConfig} 79 | 80 | HOME=~nginx ${cfg.package}/bin/nginx \ 81 | -c ${runtimeConfig} 82 | '' 83 | else 84 | '' 85 | HOME=~nginx ${cfg.package}/bin/nginx \ 86 | -c ${config} 87 | ''); 88 | enabled = true; 89 | }; 90 | 91 | users.users.${cfg.user} = mkDefaultRec { 92 | description = "Nginx"; 93 | group = cfg.group; 94 | createHome = false; 95 | home = "/var/empty"; 96 | useDefaultShell = true; 97 | uid = config.ids.uids.nginx; 98 | }; 99 | 100 | users.groups.${cfg.group} = mkDefaultRec { 101 | gid = config.ids.gids.nginx; 102 | }; 103 | }; 104 | } 105 | -------------------------------------------------------------------------------- /modules/services/pantalaimon.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.pantalaimon; 13 | 14 | dataDir = "/var/lib/pantalaimon"; 15 | in 16 | { 17 | options.services.pantalaimon = { 18 | enable = mkEnableOption "Enable pantalaimon"; 19 | 20 | package = mkOption { 21 | description = "Pantalaimon package to use"; 22 | default = pkgs.pantalaimon.override { enableDbusUi = false; }; 23 | type = types.package; 24 | }; 25 | 26 | config = mkOption { 27 | description = '' 28 | Pantalaimon configuration file in Nix form. https://github.com/matrix-org/pantalaimon/blob/master/docs/man/pantalaimon.5.md. 29 | ''; 30 | example = literalExample '' 31 | { 32 | Default = 33 | { 34 | LogLevel = "Debug"; 35 | SSL = "True"; 36 | Notifications = "On"; 37 | }; 38 | 39 | Clocktown = 40 | { 41 | Homeserver = "https://localhost:8448"; 42 | ListenAddress = "localhost" 43 | ListenPort = 8009 44 | Proxy = "http://localhost:8080"; 45 | SSL = "False"; 46 | }; 47 | } 48 | ''; 49 | type = with types; attrsOf (attrsOf (oneOf [ string int ])); 50 | apply = x: with pkgs; writeText "pantalaimon.conf" (generators.toINI { } x); 51 | }; 52 | 53 | user = mkOption { 54 | description = "User to run Pantalaimon under."; 55 | default = "pantalaimon"; 56 | type = types.str; 57 | }; 58 | 59 | group = mkOption { 60 | description = "Group to run Pantalaimon under."; 61 | default = "pantalaimon"; 62 | type = types.str; 63 | }; 64 | }; 65 | 66 | config = mkIf cfg.enable { 67 | users.users.${cfg.user} = mapAttrs (_: mkDefault) { 68 | description = "Pantalaimon"; 69 | group = cfg.group; 70 | home = "/var/empty"; 71 | createHome = false; 72 | uid = config.ids.uids.pantalaimon; 73 | }; 74 | 75 | users.groups.${cfg.group} = { 76 | gid = mkDefault config.ids.gids.pantalaimon; 77 | }; 78 | 79 | init.services.pantalaimon = 80 | { 81 | ensureSomething.create."dataDir" = { 82 | type = "directory"; 83 | mode = "770"; 84 | owner = "${cfg.user}:${cfg.group}"; 85 | dst = dataDir; 86 | persistent = true; 87 | }; 88 | 89 | script = pkgs.writeShellScript "pantalaimon-run" 90 | '' 91 | echo AAAA 92 | ${cfg.package}/bin/pantalaimon -c ${cfg.config} 93 | ''; 94 | enabled = true; 95 | }; 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /modules/services/php-fpm.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | # 9 | # This file incorporates work sublicensed from the MIT License to 10 | # Mozilla Public License, v. 2.0, for which the following copyright applies: 11 | # Copyright (c) 2003-2021 Eelco Dolstra and the Nixpkgs/NixOS contributors 12 | 13 | { pkgs, config, lib, nglib, ... }: 14 | with lib; 15 | let 16 | cfg = config.services.php-fpm; 17 | 18 | runtimeDir = "/run/php-fpm/"; 19 | 20 | genPhpIniFile = { settings, package }: pkgs.runCommandNoCC "php.ini" 21 | { 22 | phpSettings = settings; 23 | phpGlobalSettings = cfg.phpSettings; 24 | passAsFile = [ "phpSettings" "phpGlobalSettings" ]; 25 | preferLocalBuild = true; 26 | } 27 | '' 28 | cat ${package}/etc/php.ini $phpGlobalSettingsPath $phpSettingsPath > $out 29 | ''; 30 | 31 | genFpmConfFile = { settings }: pkgs.runCommandNoCC "php-fpm.conf" 32 | { 33 | fpmSettings = settings; 34 | fpmGlobalSettings = cfg.fpmSettings; 35 | passAsFile = [ "fpmSettings" "fpmGlobalSettings" ]; 36 | preferLocalBuild = true; 37 | } 38 | '' 39 | cat $fpmGlobalSettingsPath $fpmSettingsPath > $out 40 | ''; 41 | 42 | poolOpts = { name, ... }: { 43 | options = { 44 | socket = mkOption { 45 | type = types.str; 46 | readOnly = true; 47 | description = '' 48 | Path to the unix socket file on which to accept FastCGI requests. 49 | This options is read-only and managed by NixOS. 50 | ''; 51 | example = "${runtimeDir}.sock"; 52 | }; 53 | 54 | createUserGroup = mkOption { 55 | description = '' 56 | Whether to create the default user www-data 57 | and group www-data. 58 | ''; 59 | type = types.bool; 60 | default = true; 61 | }; 62 | 63 | fpmSettings = mkOption { 64 | type = with types; attrsOf (oneOf [ str int bool ]); 65 | default = { }; 66 | description = '' 67 | PHP-FPM global directives. Refer to the "List of global php-fpm.conf directives" section of 68 | 69 | for details. Note that settings names must be enclosed in quotes (e.g. 70 | "pm.max_children" instead of pm.max_children). 71 | You need not specify the options error_log or 72 | daemonize here, since they are generated by NixNG. 73 | ''; 74 | }; 75 | 76 | phpSettings = mkOption { 77 | type = with types; attrsOf (oneOf [ str int bool ]); 78 | default = { }; 79 | example = literalExample '' 80 | { 81 | "date.timezone" = "CET"; 82 | } 83 | ''; 84 | description = '' 85 | Options for PHP configuration files php.ini. 86 | ''; 87 | }; 88 | 89 | package = mkOption { 90 | type = types.package; 91 | default = pkgs.php74; 92 | description = '' 93 | The PHP package to use for running this PHP-FPM pool. 94 | ''; 95 | }; 96 | 97 | environment = mkOption { 98 | type = with types; attrsOf (oneOf [ str int bool ]); 99 | default = { }; 100 | description = '' 101 | Environment variables used for this PHP-FPM pool. 102 | ''; 103 | example = literalExample '' 104 | { 105 | HOSTNAME = "$HOSTNAME"; 106 | TMP = "/tmp"; 107 | TMPDIR = "/tmp"; 108 | TEMP = "/tmp"; 109 | } 110 | ''; 111 | }; 112 | }; 113 | 114 | config = { 115 | socket = "${runtimeDir}/${name}.sock"; 116 | fpmSettings = mapAttrs (_: mkDefault) { 117 | user = "www-data"; 118 | group = "www-data"; 119 | listen = cfg.pools.${name}.socket; 120 | "listen.owner" = "www-data"; 121 | "listen.group" = "www-data"; 122 | "listen.mode" = "0660"; 123 | }; 124 | }; 125 | }; 126 | in 127 | { 128 | options.services.php-fpm = { 129 | fpmSettings = mkOption { 130 | type = with types; attrsOf (oneOf [ str int bool ]); 131 | default = { }; 132 | apply = x: nglib.generators.php.fpm { } x "global"; 133 | description = '' 134 | PHP-FPM global directives. Refer to the "List of global php-fpm.conf directives" section of 135 | 136 | for details. Note that settings names must be enclosed in quotes (e.g. 137 | "pm.max_children" instead of pm.max_children). 138 | You need not specify the options error_log or 139 | daemonize here, since they are generated by NixNG. 140 | Each pools config will be prepended with these. 141 | ''; 142 | }; 143 | 144 | phpSettings = mkOption { 145 | type = with types; attrsOf (oneOf [ str int bool ]); 146 | default = { }; 147 | apply = nglib.generators.php.ini; 148 | example = literalExample '' 149 | { 150 | "date.timezone" = "CET"; 151 | } 152 | ''; 153 | description = '' 154 | Global options for PHP configuration files php.ini. 155 | Each pool's config will be prepended with these. 156 | ''; 157 | }; 158 | 159 | pools = mkOption { 160 | type = with types; attrsOf (submodule poolOpts); 161 | default = { }; 162 | description = '' 163 | PHP-FPM "pools", think of each pool as a separate php-fpm instance. 164 | If none are defined, the php-fpm service module does nothing. 165 | ''; 166 | }; 167 | }; 168 | 169 | config = 170 | mkIf (cfg.pools != { }) { 171 | services.php-fpm.fpmSettings = { 172 | daemonize = false; 173 | }; 174 | 175 | init.services = mapAttrs' 176 | (pool: opts: 177 | nameValuePair "php-fpm-${pool}" { 178 | enabled = true; 179 | ensureSomething.create."runtimeDir" = { 180 | type = "directory"; 181 | dst = runtimeDir; 182 | # TODO: shouldn't be persistent but we could delete a socket 183 | # from another pool 184 | persistent = true; 185 | }; 186 | script = 187 | let 188 | phpIniFile = genPhpIniFile 189 | { 190 | settings = nglib.generators.php.ini opts.phpSettings; 191 | package = opts.package; 192 | }; 193 | 194 | phpFpmConfFile = genFpmConfFile 195 | { 196 | settings = nglib.generators.php.fpm opts.environment opts.fpmSettings pool; 197 | }; 198 | in 199 | pkgs.writeShellScript "php-fpm-${pool}-run" 200 | '' 201 | echo HELLO 202 | ${opts.package}/bin/php-fpm -y ${phpFpmConfFile} -c ${phpIniFile} 203 | ''; 204 | } 205 | ) 206 | cfg.pools; 207 | 208 | users.users = builtins.listToAttrs (filter (x: x.value != null) 209 | (mapAttrsToList 210 | (pool: opts: 211 | let 212 | user = opts.phpSettings.user; 213 | in 214 | nameValuePair user 215 | (if opts.createUserGroup then 216 | { 217 | description = "PHP-FPM - ${pool}"; 218 | group = user; 219 | createHome = false; 220 | home = "/var/empty"; 221 | useDefaultShell = true; 222 | uid = config.ids.uids.${user}; 223 | } 224 | else 225 | null) 226 | ) 227 | cfg.pools)); 228 | 229 | users.groups = builtins.listToAttrs (filter (x: x.value != null) 230 | (mapAttrsToList 231 | (pool: opts: 232 | let 233 | group = opts.phpSettings.group; 234 | in 235 | nameValuePair group 236 | (if opts.createUserGroup then 237 | { 238 | gid = config.ids.gids.${group}; 239 | } 240 | else 241 | null) 242 | ) 243 | cfg.pools)); 244 | }; 245 | } 246 | -------------------------------------------------------------------------------- /modules/services/socklog.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { config, lib, pkgs, ... }: 10 | with lib; 11 | let 12 | cfg = config.services.socklog; 13 | in 14 | { 15 | options.services.socklog = { 16 | enable = mkEnableOption "Enable socklog."; 17 | 18 | unix = mkOption { 19 | description = "Make socklog listen on a unix domain socket. Input the path to the UDS socklog should use."; 20 | type = with types; nullOr path; 21 | default = null; 22 | }; 23 | inet = mkOption { 24 | description = "Make socklog listen on UDP."; 25 | type = with types; nullOr (submodule { 26 | options = { 27 | ip = mkOption { 28 | description = '' 29 | The IP address on which to listen on, must be an interface 30 | or 0 for all. Doesn't accept `localhost`. 31 | ''; 32 | type = types.str; 33 | default = "127.0.0.1"; 34 | }; 35 | port = mkOption { 36 | description = "The port on which to listen on."; 37 | type = types.port; 38 | default = 514; 39 | }; 40 | }; 41 | }); 42 | default = null; 43 | }; 44 | }; 45 | config = mkIf cfg.enable { 46 | init.services.socklog = 47 | let 48 | unixSocklog = 49 | optionalString (cfg.unix != null) "socklog unix ${cfg.unix} &"; 50 | inetSocklog = 51 | optionalString (cfg.inet != null) "socklog inter ${cfg.inet.ip} ${toString cfg.inet.port} &"; 52 | in 53 | { 54 | script = pkgs.writeShellScript "socklog-run" '' 55 | set -m 56 | 57 | export PATH=${pkgs.socklog}/bin:$PATH 58 | 59 | trap 'kill %1; kill %2' SIGINT SIGTERM 60 | ${unixSocklog} 61 | ${inetSocklog} 62 | fg 63 | ''; 64 | enabled = true; 65 | }; 66 | 67 | assertions = [ 68 | { 69 | assertion = !(cfg.unix == null && cfg.inet == null); 70 | message = "You must select at least one listening endpoint for socklog, either `unix` or `inet`"; 71 | } 72 | ]; 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /modules/services/zigbee2mqtt.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, config, lib, nglib, ... }: 10 | with nglib; with lib; 11 | let 12 | cfg = config.services.zigbee2mqtt; 13 | format = pkgs.formats.yaml {}; 14 | 15 | configDir = pkgs.runCommandNoCC "zigbee2mqtt-config-dir" {} 16 | '' 17 | mkdir -p $out 18 | ln -s ${format.generate "configuration.yaml" cfg.config} $out/configuration.yaml 19 | ''; 20 | in 21 | { 22 | options.services.zigbee2mqtt = { 23 | enable = mkEnableOption "Enable zigbee2mqtt."; 24 | 25 | package = mkOption { 26 | type = with types; package; 27 | default = pkgs.zigbee2mqtt; 28 | description = '' 29 | Which zigbee2mqtt package to use. 30 | ''; 31 | }; 32 | 33 | config = mkOption { 34 | type = format.type; 35 | default = {}; 36 | description = '' 37 | Home Assistant configuration, https://www.home-assistant.io/docs/configuration/. 38 | ''; 39 | }; 40 | 41 | user = mkOption { 42 | description = "zigbee2mqtt user."; 43 | type = types.str; 44 | default = "zigbee2mqtt"; 45 | }; 46 | 47 | group = mkOption { 48 | description = "zigbee2mqtt group."; 49 | type = types.str; 50 | default = "zigbee2mqtt"; 51 | }; 52 | 53 | envsubst = mkEnableOption "Run envsubst on the configuration file."; 54 | }; 55 | 56 | config = mkIf cfg.enable { 57 | services.zigbee2mqtt.config = mkDefaultRec 58 | { 59 | http.server_port = "8123"; 60 | }; 61 | 62 | init.services.zigbee2mqtt = { 63 | script = pkgs.writeShellScript "zigbee2mqtt-run" 64 | '' 65 | mkdir -p /var/zigbee2mqtt/ 66 | cp '${configDir}'/* /var/zigbee2mqtt/ 67 | ${optionalString cfg.envsubst 68 | '' 69 | rm /var/zigbee2mqtt/configuration.yaml 70 | ${pkgs.envsubst}/bin/envsubst \ 71 | < '${configDir}/configuration.yaml' \ 72 | > /var/zigbee2mqtt/configuration.yaml 73 | '' 74 | } 75 | 76 | chown -R ${cfg.user}:${cfg.group} /var/zigbee2mqtt/ 77 | chmod -R u=rwX,g=r-X,o= /var/zigbee2mqtt/ 78 | 79 | ZIGBEE2MQTT_DATA="/var/zigbee2mqtt/" chpst -u ${cfg.user}:${cfg.group} -b zigbee2mqtt ${cfg.package}/bin/zigbee2mqtt 80 | ''; 81 | enabled = true; 82 | }; 83 | 84 | users.users.${cfg.user} = mkDefaultRec { 85 | description = "zigbee2mqtt"; 86 | group = cfg.group; 87 | createHome = false; 88 | home = "/var/empty"; 89 | useDefaultShell = true; 90 | uid = config.ids.uids.zigbee2mqtt; 91 | }; 92 | 93 | users.groups.${cfg.group} = mkDefaultRec { 94 | gid = config.ids.gids.zigbee2mqtt; 95 | }; 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /modules/system.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { pkgs, lib, nglib, config, ... }: 10 | with lib; 11 | let 12 | cfg = config.system; 13 | 14 | configFinal = config; 15 | in 16 | { 17 | options.system = { 18 | createNixRegistration = mkEnableOption 19 | '' 20 | Create $out/registration, which allows one to create and populate 21 | the Nix database at start up, useful when building container images, 22 | which must be able to use Nix themselves. 23 | ''; 24 | 25 | build = { 26 | toplevel = mkOption { 27 | description = '' 28 | The full system, built up. 29 | ''; 30 | type = types.path; 31 | }; 32 | 33 | ociImage = mkOption { 34 | description = '' 35 | OCI compatible image. 36 | ''; 37 | type = types.submodule { 38 | options = { 39 | build = mkOption { 40 | description = '' 41 | A path to a OCI image in a gziped tarball. 42 | ''; 43 | type = types.path; 44 | }; 45 | stream = mkOption { 46 | description = '' 47 | A script which builds an OCI image and outputs what it builds 48 | into stdout without saving to disk. 49 | ''; 50 | type = types.path; 51 | }; 52 | }; 53 | }; 54 | }; 55 | }; 56 | 57 | activation = mkOption { 58 | description = '' 59 | A set of shell script fragments that are executed when a NixNG system 60 | configuration is activated. You can update /etc, 61 | create accounts, and so on. For creating service related directories or file, 62 | please use . 63 | These fragments are isolated and can't effect each other's environment. 64 | These are run every time the system configuration is activated, which also 65 | happens at boot, therefore it's important that these scripts are idempotent 66 | and fast. 67 | ''; 68 | type = with types; attrsOf (submodule { 69 | options = { 70 | data = mkOption { 71 | description = '' 72 | Script fragment which to run. 73 | ''; 74 | type = types.str; 75 | }; 76 | before = mkOption { 77 | description = '' 78 | Script before dependencies. See /lib/dag.nix. 79 | ''; 80 | type = with types; listOf str; 81 | }; 82 | after = mkOption { 83 | description = '' 84 | Script after dependencies. See /lib/dag.nix 85 | ''; 86 | type = with types; listOf str; 87 | }; 88 | }; 89 | }); 90 | apply = x: nglib.dag.dagTopoSort x; 91 | default = { }; 92 | }; 93 | activationScript = mkOption { 94 | description = '' 95 | Script generated from , used to setup the environment. 96 | ''; 97 | type = types.path; 98 | readOnly = true; 99 | }; 100 | 101 | name = mkOption { 102 | description = "System name, used when generating container images"; 103 | default = "nixng"; 104 | type = types.str; 105 | }; 106 | }; 107 | 108 | config = { 109 | system.build = { 110 | toplevel = pkgs.runCommandNoCC "nixng" 111 | { nativeBuildInputs = with pkgs; [ busybox makeWrapper ]; } 112 | (with configFinal; 113 | let 114 | closureInfo = pkgs.closureInfo 115 | { rootPaths = [ configFinal.init.script system.activationScript ]; }; 116 | in 117 | '' 118 | mkdir $out 119 | 120 | # Substitute in the path to the system closure to avoid 121 | # an infinite dep cycle 122 | substitute ${init.script} $out/init \ 123 | --subst-var-by "systemConfig" "$out" 124 | substitute ${system.activationScript} $out/activation \ 125 | --subst-var-by "systemConfig" "$out" 126 | chmod +x $out/init $out/activation 127 | 128 | # 129 | ${optionalString system.createNixRegistration 130 | "ln -s ${closureInfo}/registration $out/registration"} 131 | ''); 132 | 133 | ociImage = 134 | let 135 | config = { 136 | name = cfg.name; 137 | tag = "latest"; 138 | maxLayers = 125; 139 | 140 | config = { 141 | StopSignal = "SIGCONT"; 142 | Entrypoint = 143 | [ 144 | "${configFinal.system.build.toplevel}/init" 145 | ]; 146 | }; 147 | }; 148 | in 149 | with pkgs; { 150 | build = dockerTools.buildLayeredImage config; 151 | stream = dockerTools.streamLayeredImage config; 152 | }; 153 | }; 154 | 155 | system.activation.currentSystem = nglib.dag.dagEntryAnywhere 156 | '' 157 | export PATH=${pkgs.busybox}/bin 158 | 159 | mkdir -p /run 160 | ln -s $_system_config /run/current-system 161 | ''; 162 | 163 | system.activationScript = pkgs.writeShellScript "activation" 164 | '' 165 | ## Set path to the system closure 166 | ## This is substituted in from `top-level` 167 | _system_config="@systemConfig@" 168 | 169 | _status=0 170 | trap "_status=1 _localstatus=\$?" ERR 171 | 172 | ${concatStringsSep "\n" (map (dag: 173 | '' 174 | _localstatus=0 175 | echo "Running activation script ${dag.name}" 176 | ( 177 | unset PATH 178 | ${dag.data} 179 | ) 180 | if (( _localstatus > 0 )); then 181 | printf "Activation script snippet '%s' failed (%s)\n" "${dag.name}" "$_localstatus" 182 | fi 183 | '' 184 | ) cfg.activation.result)} 185 | 186 | exit $_status 187 | ''; 188 | 189 | assertions = [ 190 | { 191 | assertion = !(cfg.activation ? "cycle" || cfg.activation ? "loops"); 192 | message = '' 193 | `cfg.activation` has one or more cycles and/or loops. 194 | - cycles: 195 | ${(map (x: "{ after = [ ${concatSepStrings " " x.after} ]; data = ${x.data}; name = ${x.name} }") cfg.activation.loops or []) or ""} 196 | - loops: 197 | ${(map (x: "{ after = [ ${concatSepStrings " " x.after} ]; data = ${x.data}; name = ${x.name} }") cfg.activation.loops or [])} 198 | ''; 199 | } 200 | ]; 201 | }; 202 | } 203 | -------------------------------------------------------------------------------- /modules/users.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { nglib, lib, pkgs, config, ... }: 10 | with lib; 11 | let 12 | ids = config.ids; 13 | cfg = config.users; 14 | 15 | userOpts = { config, ... }: { 16 | options = { 17 | uid = mkOption { 18 | description = "The account UID."; 19 | type = types.int; 20 | }; 21 | group = mkOption { 22 | description = "The user's primary group."; 23 | type = types.str; 24 | default = "nogroup"; 25 | }; 26 | home = mkOption { 27 | description = "The user's home."; 28 | type = types.path; 29 | default = "/var/empty"; 30 | }; 31 | shell = mkOption { 32 | description = "The user's default shell."; 33 | type = types.path; 34 | default = "${pkgs.busybox}/bin/nologin"; 35 | }; 36 | createHome = mkOption { 37 | description = '' 38 | Whether to create the user's home directory automatically or not, 39 | if the home directory exists but is not owned by the user and their 40 | group, it will be chowned to match. 41 | ''; 42 | type = types.bool; 43 | default = true; 44 | }; 45 | description = mkOption { 46 | description = "The user's description."; 47 | type = types.str; 48 | default = ""; 49 | }; 50 | extraGroups = mkOption { 51 | description = "The user's auxiliary groups."; 52 | type = types.listOf types.str; 53 | default = [ ]; 54 | }; 55 | 56 | useDefaultShell = mkOption { 57 | description = '' 58 | If true, the user's shell will be set to . 59 | ''; 60 | type = types.bool; 61 | default = false; 62 | }; 63 | isNormalUser = mkOption { 64 | description = '' 65 | Indicates whether this is an account for a 'real' user. This automatically sets 66 | to users, 67 | to true, to /home/username, 68 | and to true. 69 | ''; 70 | type = types.bool; 71 | default = false; 72 | }; 73 | 74 | hashedPassword = mkOption { 75 | description = '' 76 | Specifies the hashed password for the user, options 77 | and are mutually exclusive and can't be set both 78 | at the same time. Use mkpasswd -m sha-512 to create a suitable hash. 79 | 80 | Be careful, the hash isn't checked for format errors and therefore by 81 | inputing a wrongly formatted hash you can yourself out!! 82 | ''; 83 | type = types.nullOr types.str; 84 | default = null; 85 | }; 86 | hashedPasswordFile = mkOption { 87 | description = '' 88 | Specifies the file containing the user's hashed password, options 89 | and are mutually exclusive 90 | and can't be set both at the same time. Use mkPasswd -m sha-512 91 | to create a suitable hash. The file should contain one line on 92 | which the password hash is specified. 93 | 94 | Be careful, the hash isn't checked for format errors and therefore by 95 | inputing a wrongly formatted hash you can yourself out!! 96 | ''; 97 | type = types.nullOr types.str; 98 | default = null; 99 | }; 100 | }; 101 | 102 | config = mkIf config.isNormalUser { 103 | group = mkDefault "users"; 104 | createHome = mkDefault true; 105 | home = mkDefault "/home/${config.name}"; 106 | useDefaultShell = mkDefault true; 107 | }; 108 | }; 109 | in 110 | { 111 | options.users = { 112 | defaultUserShell = mkOption { 113 | description = "The default normal user shell."; 114 | type = types.either types.shellPackage types.path; 115 | default = "${pkgs.bashInteractive}/bin/bash"; 116 | }; 117 | 118 | createDefaultUsersGroups = mkOption { 119 | description = '' 120 | Whether to create useful users and groups. Creates the users: 121 | root, nobody 122 | And groups: 123 | root, nogroup 124 | ''; 125 | type = types.bool; 126 | default = true; 127 | }; 128 | 129 | users = mkOption { 130 | description = "An attributes set of users to be created."; 131 | type = types.attrsOf (types.submodule userOpts); 132 | default = { }; 133 | }; 134 | 135 | groups = mkOption { 136 | description = "An attributes set of groups to be created."; 137 | type = types.attrsOf (types.submodule { 138 | options = { 139 | gid = mkOption { 140 | description = "Group GID."; 141 | type = types.int; 142 | }; 143 | members = mkOption { 144 | description = '' 145 | The user names of the group members, added to the 146 | /etc/group file. 147 | ''; 148 | type = with types; listOf str; 149 | default = [ ]; 150 | }; 151 | }; 152 | }); 153 | default = { }; 154 | }; 155 | 156 | passwdFile = mkOption { 157 | description = "Generate /etc/passwd file."; 158 | type = types.path; 159 | readOnly = true; 160 | }; 161 | groupFile = mkOption { 162 | description = "Generate /etc/group file."; 163 | type = types.path; 164 | readOnly = true; 165 | }; 166 | generateShadow = mkOption { 167 | description = '' 168 | An executable, which when run generates /etc/shadow 169 | to stdout. Used during activation to avoid the inclusion of the 170 | /etc/shadow file in the world readable Nix store. 171 | ''; 172 | type = types.path; 173 | readOnly = true; 174 | }; 175 | }; 176 | 177 | config = { 178 | assertions = flatten (mapAttrsToList 179 | (n: v: 180 | [ 181 | { 182 | assertion = !(v.hashedPassword != null && v.hashedPasswordFile != null); 183 | message = "For user ${n} either `hashedPassword`, `hashedPasswordFile`, none must be non-null, but not both."; 184 | } 185 | { 186 | assertion = cfg.groups ? "${v.group}"; 187 | message = "For user ${n} the group ${v.group} does not exist!"; 188 | } 189 | ] ++ 190 | (map 191 | (group: 192 | { 193 | assertion = cfg.groups ? v.group; 194 | message = "For user ${n} the extra group ${group} does not exist!"; 195 | } 196 | ) 197 | v.extraGroups) 198 | ) 199 | cfg.users); 200 | 201 | system.activation."users" = 202 | let 203 | createHomes = 204 | concatMapStringsSep "\n" 205 | ({ n, v }: "mkdir -p ${v.home} && chown ${n}:${v.group} ${v.home}") 206 | (filter ({ v, ... }: v.createHome) 207 | (mapAttrsToList (n: v: { n = n; v = v; }) cfg.users)); 208 | in 209 | nglib.dag.dagEntryAnywhere '' 210 | export PATH=${pkgs.busybox}/bin 211 | 212 | ln -sf ${cfg.passwdFile} /etc/passwd 213 | ln -sf ${cfg.groupFile} /etc/group 214 | ${cfg.generateShadow} > /etc/shadow 215 | ${createHomes} 216 | ''; 217 | 218 | users = { 219 | users = mkIf cfg.createDefaultUsersGroups { 220 | root = { 221 | uid = ids.uids.root; 222 | group = "root"; 223 | createHome = true; 224 | home = "/root"; 225 | useDefaultShell = true; 226 | }; 227 | nobody = { 228 | uid = ids.uids.nobody; 229 | group = "nogroup"; 230 | createHome = true; 231 | home = "/var/empty"; 232 | shell = "${pkgs.busybox}/bin/nologin"; 233 | }; 234 | }; 235 | 236 | groups = mkMerge ([ 237 | (optionalAttrs cfg.createDefaultUsersGroups { 238 | root.gid = ids.gids.root; 239 | nogroup.gid = ids.gids.nogroup; 240 | }) 241 | ] ++ 242 | ( 243 | let 244 | filterGroups = groups: 245 | filter (group: cfg.groups ? "${group}") groups; 246 | members = flatten (mapAttrsToList (n: u: map (g: { "${g}".members = [ n ]; }) (u.extraGroups ++ singleton u.group)) cfg.users); 247 | in 248 | members 249 | )); 250 | 251 | passwdFile = pkgs.writeText "passwd" 252 | (concatStringsSep "\n" (mapAttrsToList 253 | (n: v: 254 | with v; 255 | let 256 | shell = if useDefaultShell then cfg.defaultUserShell else v.shell; 257 | in 258 | "${n}:x:${toString uid}:${toString cfg.groups."${group}".gid}:${description}:${home}:${shell}" 259 | ) 260 | cfg.users)); 261 | groupFile = pkgs.writeText "group" 262 | (concatStringsSep "\n" (mapAttrsToList 263 | (n: v: 264 | with v; 265 | "${n}:x:${toString gid}:${concatStringsSep "," members}" 266 | ) 267 | cfg.groups)); 268 | generateShadow = pkgs.writeShellScript "generate-shadow" 269 | '' 270 | export PATH=${pkgs.busybox}/bin 271 | cat << EOF 272 | ${concatStringsSep "\n" (mapAttrsToList (n: v: 273 | with v; 274 | "${n}:${if hashedPassword != null then hashedPassword else if hashedPasswordFile != null then "$(<${hashedPasswordFile})" else "!"}:1::::::" 275 | ) cfg.users)} 276 | EOF 277 | ''; 278 | }; 279 | }; 280 | } 281 | -------------------------------------------------------------------------------- /nix-ng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicRB/NixNG/c4cccbe2c315bfcb260648f32387d1c88668e4a8/nix-ng.png -------------------------------------------------------------------------------- /nix-ng.png.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | 3 | SPDX-License-Identifier: CC-BY-SA-4.0 -------------------------------------------------------------------------------- /overlay/cronie.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { stdenv, lib, fetchurl }: 10 | stdenv.mkDerivation { 11 | name = "cronie"; 12 | version = "1.5.7"; 13 | 14 | configureFlags = "--localstatedir=/var --sysconfdir=/etc"; 15 | 16 | src = fetchurl { 17 | url = "https://github.com/cronie-crond/cronie/releases/download/cronie-1.5.7/cronie-1.5.7.tar.gz"; 18 | sha256 = "sha256-U4vPry6Yblrh7fbRRyp36oJx1qkAWu4kl6ntbhMyDrM="; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /overlay/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | self: super: 10 | let 11 | inherit (super) haskell callPackage; 12 | in 13 | { 14 | tinyLinux = callPackage ./tiny-linux.nix { }; 15 | runVmLinux = callPackage ./run-vm-linux.nix { }; 16 | cronie = callPackage ./cronie.nix { }; 17 | sigell = haskell.packages."ghc884".callPackage ./sigell/cabal.nix { }; 18 | 19 | inherit (callPackage ./trivial-builders.nix {}) 20 | writeSubstitutedFile 21 | writeSubstitutedShellScript 22 | writeSubstitutedShellScriptBin; 23 | } 24 | -------------------------------------------------------------------------------- /overlay/run-vm-linux.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { callPackage 10 | , lib 11 | , tinyLinux 12 | }: 13 | tinyLinux.override { 14 | extraConfig = { 15 | CONFIG_NET_9P = "y"; 16 | CONFIG_NET_9P_VIRTIO = "y"; 17 | CONFIG_NET_9P_DEBUG = "y"; # perhaps? 18 | CONFIG_9P_FS = "y"; 19 | CONFIG_9P_FS_POSIX_ACL = "y"; 20 | 21 | CONFIG_NETWORK_FILESYSTEMS = "y"; 22 | CONFIG_INET = "y"; 23 | CONFIG_NET = "y"; 24 | CONFIG_9P = "y"; 25 | 26 | CONFIG_VIRTIO = "y"; 27 | 28 | CONFIG_PCI = "y"; 29 | CONFIG_VIRTIO_PCI = "y"; 30 | CONFIG_VIRTIO_MENU = "y"; 31 | CONFIG_PCI_HOST_GENERIC = "y"; # (only needed for the QEMU Arm 'virt' board) from wikipedia 32 | 33 | # TTY stuff 34 | CONFIG_TTY = "y"; 35 | CONFIG_VT = "y"; 36 | CONFIG_VT_CONSOLE = "y"; 37 | CONFIG_UNIX98_PTYS = "y"; 38 | CONFIG_LEGACY_PTYS = "y"; 39 | CONFIG_LEGACY_PTY_COUNT = "256"; 40 | CONFIG_LDISC_AUTOLOAD = "y"; 41 | 42 | # Serial console, makes it work in QEMU 43 | CONFIG_SERIAL_8250 = "y"; 44 | CONFIG_SERIAL_8250_CONSOLE = "y"; 45 | 46 | # Debug logs during boot are always handy 47 | CONFIG_PRINTK = "y"; 48 | 49 | # Initrd things, perhaps make the compression configurable? 50 | CONFIG_BLK_DEV_INITRD = "y"; 51 | CONFIG_RD_GZIP = "y"; 52 | CONFIG_RD_BZIP2 = "n"; 53 | CONFIG_RD_LZMA = "n"; 54 | CONFIG_RD_XZ = "n"; 55 | CONFIG_RD_LZO = "n"; 56 | CONFIG_RD_LZ4 = "n"; 57 | 58 | # Required for shebangs 59 | CONFIG_BINFMT_ELF = "y"; # general execution 60 | CONFIG_BINFMT_SCRIPT = "y"; # bash shebang 61 | 62 | # Required for runit 63 | CONFIG_FILE_LOCKING = "y"; 64 | 65 | # futex 66 | CONFIG_FUTEX = "y"; 67 | 68 | ## Filesystems 69 | # proc 70 | CONFIG_PROC_FS = "y"; 71 | CONFIG_PROC_SYSCTL = "y"; 72 | CONFIG_PROC_PAGE_MONITOR = "n"; 73 | # sys 74 | CONFIG_SYSFS = "y"; 75 | # devtmpfs 76 | CONFIG_DEVTMPFS = "y"; 77 | 78 | # overlayfs 79 | CONFIG_EXPORTFS = "y"; 80 | CONFIG_OVERLAY_FS = "y"; 81 | CONFIG_OVERLAY_FS_INDEX = "y"; 82 | CONFIG_OVERLAY_FS_METACOPY = "y"; 83 | 84 | # loop devices 85 | CONFIG_BLK_DEV = "y"; 86 | CONFIG_BLK_DEV_LOOP = "y"; 87 | CONFIG_BLK_DEV_LOOP_MIN_COUNT = "4"; 88 | 89 | # filesystems 90 | CONFIG_BLOCK = "y"; 91 | CONFIG_EXT4_FS = "y"; 92 | CONFIG_EXT4_FS_POSIX_ACL = "y"; 93 | 94 | CONFIG_VFAT_FS = "y"; 95 | CONFIG_NLS_CODEPAGE_437 = "y"; # why? cause "FAT-fs (loop0p1): codepage cp437 not found" 96 | CONFIG_NLS_ISO8859_1 = "y"; # same here, "FAT-fs (loop0p1): IO charset iso8859-1 not found" 97 | CONFIG_FAT_FS = "y"; 98 | }; 99 | } 100 | -------------------------------------------------------------------------------- /overlay/sigell/.gitignore: -------------------------------------------------------------------------------- 1 | dist-newstyle 2 | -------------------------------------------------------------------------------- /overlay/sigell/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Revision history for sigell 2 | 3 | ## 0.1.0.0 -- YYYY-mm-dd 4 | 5 | * First version. Released on an unsuspecting world. 6 | -------------------------------------------------------------------------------- /overlay/sigell/app/CmdLine.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DeriveDataTypeable #-} 2 | 3 | module CmdLine where 4 | 5 | import System.Console.CmdArgs 6 | 7 | data CmdLine = Sample {cmdLineConfigFile :: FilePath} 8 | deriving (Show, Data, Typeable) 9 | 10 | cmdline = Sample { cmdLineConfigFile = def &= args &= typFile } 11 | -------------------------------------------------------------------------------- /overlay/sigell/app/Config.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {-# LANGUAGE LambdaCase #-} 3 | 4 | module Config where 5 | 6 | import System.Posix.Signals (Signal, sigABRT, sigALRM, sigBUS, sigCHLD, 7 | sigCONT, sigFPE, sigHUP, sigILL, sigKILL, 8 | sigQUIT, sigSEGV, sigSTOP, sigTTIN, sigTTOU, 9 | sigUSR1, sigUSR2, sigPOLL, sigPROF, sigSYS, 10 | sigTRAP, sigURG, sigVTALRM, sigXCPU, sigXFSZ, sigTERM, sigTSTP) 11 | import Data.Aeson.Types ((.:)) 12 | import Data.Aeson as A 13 | import Data.Aeson.Types as AT 14 | import Data.Vector as V 15 | import Data.HashMap.Strict as H 16 | import GHC.Base ((<|>)) 17 | import Data.Functor 18 | 19 | data SignalSelector = Pid Int | Child 20 | deriving (Show) 21 | 22 | instance A.FromJSON SignalSelector where 23 | parseJSON (A.Object v) 24 | = v .: "type" >>= s 25 | where s :: String -> AT.Parser SignalSelector 26 | s "pid" = Pid <$> v .: "pid" 27 | s "child" = pure Child 28 | s _ = fail "Invalid SignalSelector type" 29 | 30 | data Action = Exec { actionExecCommand :: [String], 31 | actionExecEnvironment :: Maybe [(String, String)] } 32 | | Signal { actionSignalRewrite :: Maybe Signal, 33 | actionSignalSelector :: SignalSelector } 34 | deriving (Show) 35 | 36 | instance A.FromJSON Action where 37 | parseJSON (A.Object v) 38 | = v .: "type" >>= s 39 | where s :: String -> AT.Parser Action 40 | s "exec" = Exec 41 | <$> v .: "command" 42 | <*> (v .:? "environment" <&> (=<<) (pure . H.toList)) 43 | s "signal" = Signal 44 | <$> (v .: "rewrite" >>= parseSignalMaybe) <*> v .: "selector" 45 | 46 | data Entry = Entry { entrySignal :: Signal, 47 | entryAction :: Action } 48 | deriving (Show) 49 | 50 | parseSignal :: String -> AT.Parser Signal 51 | parseSignal "ABRT" = pure sigABRT 52 | parseSignal "ALRM" = pure sigALRM 53 | parseSignal "BUS" = pure sigBUS 54 | parseSignal "CHLD" = pure sigCHLD 55 | parseSignal "CONT" = pure sigCONT 56 | parseSignal "FPE" = pure sigFPE 57 | parseSignal "HUP" = pure sigHUP 58 | parseSignal "ILL" = pure sigILL 59 | parseSignal "KILL" = pure sigKILL 60 | parseSignal "QUIT" = pure sigQUIT 61 | parseSignal "SEGV" = pure sigSEGV 62 | parseSignal "STOP" = pure sigSTOP 63 | parseSignal "TERM" = pure sigTERM 64 | parseSignal "TSTP" = pure sigTSTP 65 | parseSignal "TTIN" = pure sigTTIN 66 | parseSignal "TTOU" = pure sigTTOU 67 | parseSignal "USR1" = pure sigUSR1 68 | parseSignal "USR2" = pure sigUSR2 69 | parseSignal "POLL" = pure sigPOLL 70 | parseSignal "PROF" = pure sigPROF 71 | parseSignal "SYS" = pure sigSYS 72 | parseSignal "TRAP" = pure sigTRAP 73 | parseSignal "URG" = pure sigURG 74 | parseSignal "VTALRM" = pure sigVTALRM 75 | parseSignal "XCPU" = pure sigXCPU 76 | parseSignal "XFSZ" = pure sigXFSZ 77 | parseSignal _ = fail "Invalid signal" 78 | 79 | parseSignalMaybe :: Maybe String -> Parser (Maybe Signal) 80 | parseSignalMaybe (Just s) = fmap Just (parseSignal s) 81 | parseSignalMaybe Nothing = pure Nothing 82 | 83 | instance A.FromJSON Entry where 84 | parseJSON (A.Object v) 85 | = Entry 86 | <$> (v .: "signal" >>= parseSignal) 87 | <*> v .: "action" 88 | 89 | data Config = Config { configEntries :: [Entry], 90 | configCommand :: [String], 91 | configEnvironment :: Maybe [(String, String)] } 92 | deriving (Show) 93 | 94 | instance A.FromJSON Config where 95 | parseJSON (A.Object v) 96 | = Config 97 | <$> a 98 | <*> v .: "command" 99 | <*> (v .:? "environment" <&> (=<<) (pure . H.toList)) 100 | where a = entries >>= Prelude.mapM parseJSON 101 | entries = case v H.! "entries" of 102 | A.Array v -> pure $ V.toList v 103 | _ -> fail "Config filed `entries` not of type `Array`" 104 | -------------------------------------------------------------------------------- /overlay/sigell/app/Main.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | import System.Posix.Signals 3 | import Control.Concurrent.Chan 4 | import Foreign.C (CInt) 5 | import Control.Concurrent (putMVar) 6 | 7 | import Data.Aeson (encode, eitherDecode); 8 | import Data.ByteString.Lazy.Char8 (pack); 9 | 10 | import Config 11 | import CmdLine 12 | 13 | import Data.Functor ((<&>)) 14 | import System.Posix.Process 15 | import System.Posix.Types 16 | import Control.Monad 17 | import Data.Maybe (fromMaybe) 18 | import System.Environment (setEnv) 19 | import System.Console.CmdArgs (cmdArgs) 20 | 21 | catchSignals :: [Signal] -> IO [Signal] 22 | catchSignals sigs = do 23 | chan <- newChan 24 | mapM_ (\sig -> installHandler sig (Catch $ writeSignal' sig chan) Nothing) sigs 25 | getChanContents chan 26 | where 27 | writeSignal' sig chan = do 28 | writeChan chan sig 29 | 30 | catchSignal :: ProcessID -> Entry -> IO () 31 | catchSignal child entry = do 32 | installHandler sig (Catch action) Nothing 33 | return () 34 | where sig = entrySignal entry 35 | action = case entryAction entry of 36 | Exec command env -> actionExec command env 37 | Signal rewrite selector -> case selector of 38 | Pid p -> signalProcess (fromMaybe sig rewrite) (CPid (fromIntegral p)) 39 | Child -> signalProcess (fromMaybe sig rewrite) child 40 | 41 | actionExec c env = void $ forkProcess 42 | (void $ do 43 | mapM_ (uncurry setEnv) (fromMaybe [] env) 44 | executeFile (command c) True (args c) Nothing) 45 | command = head 46 | args = tail 47 | 48 | readEOF :: String -> String 49 | readEOF s = unlines $ readEOF' $ lines s 50 | where readEOF' ("EOF":xs) = [] 51 | readEOF' (x:xs) = x : readEOF' xs 52 | 53 | readConfig :: String -> Either String Config 54 | readConfig = eitherDecode . pack 55 | 56 | forkedProg :: Config -> IO () 57 | forkedProg c = do 58 | getProcessID >>= createProcessGroupFor 59 | mapM_ (uncurry setEnv) (fromMaybe [] env) 60 | executeFile command True args Nothing 61 | where command = head $ configCommand c 62 | args = tail $ configCommand c 63 | env = configEnvironment c 64 | 65 | waitForProcess :: CPid -> IO () 66 | waitForProcess p = void $ getProcessStatus True False p 67 | 68 | main :: IO () 69 | main = do 70 | -- sigs <- catchSignals [ keyboardSignal, sigHUP, sigUSR1 ] 71 | -- mapM_ print sigs 72 | -- str <- getLine :: IO String 73 | -- putStrLn str 74 | -- print $ encode ([ 1, 2, 3 ] :: [Integer]) 75 | opts <- cmdArgs cmdline 76 | mc <- readFile (cmdLineConfigFile opts) <&> readConfig 77 | case mc of 78 | Right c -> do 79 | process <- forkProcess $ forkedProg c 80 | 81 | mapM_ (catchSignal process) $ configEntries c 82 | 83 | waitForProcess process 84 | return () 85 | Left s -> do 86 | putStrLn ("Invalid Config: " ++ s) 87 | putStrLn "Bye..." 88 | return () 89 | 90 | -------------------------------------------------------------------------------- /overlay/sigell/cabal.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { mkDerivation 10 | , aeson 11 | , base 12 | , bytestring 13 | , lib 14 | , unix 15 | , unordered-containers 16 | , vector 17 | , cmdargs 18 | }: 19 | mkDerivation { 20 | pname = "sigell"; 21 | version = "0.1.0.0"; 22 | src = ./.; 23 | isLibrary = false; 24 | isExecutable = true; 25 | executableHaskellDepends = [ 26 | aeson 27 | base 28 | bytestring 29 | unix 30 | unordered-containers 31 | vector 32 | cmdargs 33 | ]; 34 | license = "unknown"; 35 | hydraPlatforms = lib.platforms.none; 36 | } 37 | -------------------------------------------------------------------------------- /overlay/sigell/examples/1.json: -------------------------------------------------------------------------------- 1 | { 2 | "command": [ "bash", "-c", "echo $TEST ; sleep 15" ], 3 | "environment": { 4 | "TEST": "12" 5 | }, 6 | "entries": [ 7 | { 8 | "signal": "HUP", 9 | "action": { 10 | "type": "exec", 11 | "command": [ "bash", "-c", "echo asd" ] 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /overlay/sigell/examples/2.json: -------------------------------------------------------------------------------- 1 | { 2 | "command": [ "sleep", "15" ], 3 | "entries": [ 4 | { 5 | "signal": "USR1", 6 | "action": { 7 | "type": "signal", 8 | "rewrite": "TERM", 9 | "selector": { 10 | "type": "child" 11 | } 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /overlay/sigell/hie.yaml: -------------------------------------------------------------------------------- 1 | cradle: 2 | cabal: 3 | component: "exe:sigell" 4 | -------------------------------------------------------------------------------- /overlay/sigell/sigell.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 2.4 2 | name: sigell 3 | version: 0.1.0.0 4 | 5 | -- A short (one-line) description of the package. 6 | -- synopsis: 7 | 8 | -- A longer description of the package. 9 | -- description: 10 | 11 | -- A URL where users can report bugs. 12 | -- bug-reports: 13 | 14 | -- The license under which the package is released. 15 | -- license: 16 | author: Magic_RB 17 | maintainer: magic_rb@redalder.org 18 | 19 | -- A copyright notice. 20 | -- copyright: 21 | -- category: 22 | extra-source-files: CHANGELOG.md 23 | 24 | executable sigell 25 | main-is: Main.hs 26 | 27 | -- Modules included in this executable, other than Main. 28 | other-modules: Config, 29 | CmdLine 30 | 31 | -- LANGUAGE extensions used by modules in this package. 32 | -- other-extensions: 33 | ghc-options: -threaded 34 | build-depends: base >=4.13.0.0, 35 | aeson ^>=1.5.6.0, 36 | unix ^>=2.7.2.2, 37 | vector ^>=0.12.1.2, 38 | bytestring ^>=0.10.10.0, 39 | unordered-containers ^>=0.2.10.0, 40 | cmdargs ^>=0.10.20 41 | hs-source-dirs: app 42 | default-language: Haskell2010 43 | -------------------------------------------------------------------------------- /overlay/tiny-linux.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | # TODO use linuxManualConfig instead of buildLinux 10 | 11 | { buildLinux 12 | , linux 13 | , pkg-config 14 | , ncurses 15 | , writeText 16 | , runCommand 17 | , lib 18 | , extraConfig ? { } 19 | }: 20 | let 21 | configfile = writeText "config" '' 22 | ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "${n}=${v}") extraConfig)} 23 | ''; 24 | origKernel = buildLinux { 25 | inherit (linux) src version stdenv; 26 | inherit configfile; 27 | 28 | kernelPatches = [ ]; 29 | allowImportFromDerivation = true; 30 | }; 31 | self = 32 | origKernel.overrideAttrs (old: { 33 | buildFlags = [ 34 | "KBUILD_BUILD_VERSION=1-NixNG" 35 | "bzImage" 36 | "vmlinux" 37 | ]; 38 | configurePhase = '' 39 | runHook preConfigure 40 | 41 | mkdir build 42 | export buildRoot="$(pwd)/build" 43 | 44 | echo "manual-config configurePhase buildRoot=$buildRoot pwd=$PWD" 45 | 46 | runHook postConfigure 47 | 48 | # make $makeFlags "''${makeFlagsArray[@]}" mrproper 49 | 50 | make $makeFlags "''${makeFlagsArray[@]}" tinyconfig 51 | if [[ -f $buildRoot/.config ]] ; then 52 | cat ${configfile} >> $buildRoot/.config 53 | cat $buildRoot/.config 54 | else 55 | echo "$buildRoot/.config is empty, not appending" 56 | exit 1 57 | fi 58 | echo $buildFlags 59 | 60 | # make $makeFlags "''${makeFlagsArray[@]}" prepare 61 | 62 | # Note: https://github.com/NixOS/nixpkgs/blob/9c213398b312e0f0bb9cdf05090fd20223a82ad0/pkgs/os-specific/linux/kernel/manual-config.nix#L166 63 | buildFlagsArray+=("KBUILD_BUILD_TIMESTAMP=$(date -u -d @$SOURCE_DATE_EPOCH)") 64 | 65 | ls build 66 | ''; 67 | 68 | buildPhase = ""; 69 | 70 | postInstall = ""; 71 | 72 | nativeBuildInputs = old.nativeBuildInputs ++ [ pkg-config ncurses ]; 73 | }); 74 | in 75 | self 76 | -------------------------------------------------------------------------------- /overlay/trivial-builders.nix: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors 2 | # 3 | # SPDX-License-Identifier: MPL-2.0 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | { runCommandNoCCLocal 10 | , busybox 11 | , runtimeShell 12 | }: 13 | { 14 | writeSubstitutedShellScript = 15 | { name 16 | , file 17 | , substitutes 18 | }: 19 | runCommandNoCCLocal name 20 | ({ 21 | nativeBuildInputs = [ busybox ]; 22 | } // substitutes) 23 | '' 24 | TMPFILE=$(mktemp) 25 | substituteAll ${file} $TMPFILE 26 | touch $out 27 | echo "#! ${runtimeShell}" > $out 28 | cat $TMPFILE >> $out 29 | chmod +x $out 30 | ''; 31 | 32 | writeSubstitutedShellScriptBin = 33 | { name 34 | , file 35 | , substitutes 36 | }: 37 | runCommandNoCCLocal name 38 | ({ 39 | nativeBuildInputs = [ busybox ]; 40 | } // substitutes) 41 | '' 42 | TMPFILE=$(mktemp) 43 | substituteAll ${file} $TMPFILE 44 | mkdir -p $out/bin && touch $out/bin/${name} 45 | echo "#! ${runtimeShell}" > $out/bin/${name} 46 | cat $TMPFILE >> $out/bin/${name} 47 | chmod +x $out/bin/${name} 48 | ''; 49 | 50 | 51 | writeSubstitutedFile = 52 | { name 53 | , file 54 | , substitutes 55 | }: 56 | runCommandNoCCLocal name 57 | ({ 58 | nativeBuildInputs = [ busybox ]; 59 | } // substitutes) 60 | '' 61 | TMPFILE=$(mktemp) 62 | substituteAll ${file} $TMPFILE 63 | touch $out 64 | cat $TMPFILE >> $out 65 | ''; 66 | } 67 | --------------------------------------------------------------------------------