diff --git a/doc/.gitignore b/doc/.gitignore deleted file mode 100644 index 081b57cd..00000000 --- a/doc/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -/src/options.md -/src/packages.md -book - -/.quarto/ -/_site diff --git a/doc/_quarto.yml b/doc/_quarto.yml deleted file mode 100644 index ff754c8f..00000000 --- a/doc/_quarto.yml +++ /dev/null @@ -1,97 +0,0 @@ -project: - type: website - -website: - title: "EPNix documentation" - description: "Build, package EPICS IOCs and more using the Nix package manager" - favicon: ./logo.svg - repo-url: "https://github.com/epics-extensions/EPNix" - repo-actions: [issue] - page-navigation: true - reader-mode: true - navbar: - search: true - logo: ./logo.svg - left: - - text: "EPICS IOCs" - file: ./ioc/introduction.md - - text: "Packages" - file: ./pkgs/introduction.md - - text: "NixOS" - file: ./nixos/introduction.md - sidebar: - - title: EPICS IOCs - contents: - - text: Introduction - file: ./ioc/introduction.md - - section: User Tutorials - file: ./ioc/tutorials.md - contents: - - ./ioc/tutorials/pre-requisites.md - - ./ioc/tutorials/streamdevice.md - - ./ioc/tutorials/porting.md - - ./ioc/tutorials/day-to-day-dev.md - - ./ioc/tutorials/integration-tests.md - - ./ioc/tutorials/creating-a-mock-server.md - - ./ioc/tutorials/adding-options.md - - file: ./ioc/guides.md - contents: - - ./ioc/guides/private-repo-setup.md - - ./ioc/guides/flake-registry.md - - ./ioc/guides/developing-modules.md - - ./ioc/guides/pinning.md - - ./ioc/guides/override-package.md - - section: Testing - file: ./ioc/guides/testing.md - contents: - - ./ioc/guides/testing/packaging-python-scripts.md - - ./ioc/guides/testing/unit-tests.md - - file: ./ioc/explanations.md - - file: ./ioc/developer-tutorials.md - - file: ./ioc/developer-guides.md - contents: - - ./ioc/developer-guides/packaging-modules.md - - ./ioc/developer-guides/guidelines.md - - ./ioc/developer-guides/packaging.md - - ./ioc/developer-guides/glossary.md - - file: ./ioc/references.md - contents: - - ./ioc/references/options.md - - ./ioc/references/packages.md - - ./ioc/faq.md - - title: Packages - contents: - - text: Introduction - file: ./pkgs/introduction.md - - section: References - contents: - - ./pkgs/packages.md - - title: NixOS - contents: - - title: NixOS - file: ./nixos/introduction.md - - section: Tutorials - contents: - - ./nixos/tutorials/archiver-appliance.md - - section: User Guides - contents: - - ./nixos/guides/ca-gateway.md - - ./nixos/guides/phoebus-alarm.md - - ./nixos/guides/phoebus-save-and-restore.md - - section: Explanations - - section: References - contents: - - ./nixos/options.md - -format: - html: - theme: - light: simplex - dark: darkly - highlight-style: gruvbox - number-sections: false - reference-location: margin - citation-location: margin - code-copy: true - toc: true - shift-heading-level-by: 1 diff --git a/doc/index.md b/doc/index.md deleted file mode 100644 index d67fb159..00000000 --- a/doc/index.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: EPNix documentation ---- - -![](./logo.svg){width=70% fig-align=center} - -# Introduction - -EPNix (pronunciation: like you are high on mushrooms) packages EPICS-related software using the [Nix] package manager. - -It's made of three parts: - -- the EPICS IOC framework -- other EPICS-related packages -- NixOS modules - -The EPICS IOC framework lets you package, deploy, and test EPICS IOCs using the Nix package manager, which provides several benefits. -For more information, see the [EPICS IOCs introduction]. - -EPNix also packages other EPICS-related tools, like procServ, Phoebus, etc. -You can build them using Nix, and in the future download them pre-compiled, while having a strong guarantee that they will work as-is. -For a list of all supported EPICS-related packages, see the [Packages list]. - -EPNix also provides NixOS modules, which are instructions on how to configure various EPICS-related services on NixOS machines (for example the Phoebus alarm server). -EPNix strives to have integration tests for each of those module. -For more information, see the [NixOS modules introduction]. - - [Nix]: https://nixos.org/guides/how-nix-works.html - [EPICS IOCs introduction]: ./ioc/introduction.md - [Packages list]: ./pkgs/packages.md - [NixOS modules introduction]: ./nixos/introduction.md - -# Packaging policy - -As EPNix provides a package repository, packaging for example `epics-base`, `asyn`, `StreamDevice`, `procServ`, `phoebus`, etc., it needs to have a packaging policy. - -In its package repository, EPNix officially supports the latest upstream version. - -However, since EPNix is a git repository, you will be able, through Nix, to use a fixed version of EPNix, without being forced to upgrade your dependencies. - -```{=html} - -``` - -## The epics-base package - -The epics-base package has no significant modification compared to the upstream version at [Launchpad]. -One goal of EPNix is to keep those modifications to a minimum, and upstream what's possible. - -# Release branches - -EPNix has a `master` branch, -which is considered unstable, -meaning breaking changes might happen without notice. - -EPNix also has release branches, -such as `nixos-23.11`, -tied to the nixpkgs release branches, -where breaking changes are forbidden. - -Backporting changes to older release branches is done on a "best-effort" basis. - ------------------------------------------------------------------------- - -This documentation follows the [Diátaxis] documentation framework. - - [Launchpad]: https://git.launchpad.net/epics-base - [Diátaxis]: https://diataxis.fr/ diff --git a/doc/ioc/developer-guides.md b/doc/ioc/developer-guides.md deleted file mode 100644 index 1bcdb330..00000000 --- a/doc/ioc/developer-guides.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Developer guides ---- - -This section of the documentation book contains how-to guides[^1] for contributors to the EPNix project, related to building and deploying EPICS IOCs. - -[^1]: diff --git a/doc/ioc/developer-guides/glossary.md b/doc/ioc/developer-guides/glossary.md deleted file mode 100644 index f46edec5..00000000 --- a/doc/ioc/developer-guides/glossary.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Glossary ---- - -TODO diff --git a/doc/ioc/developer-guides/guidelines.md b/doc/ioc/developer-guides/guidelines.md deleted file mode 100644 index aa6e3dce..00000000 --- a/doc/ioc/developer-guides/guidelines.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Guidelines ---- - -TODO diff --git a/doc/ioc/developer-guides/packaging-modules.md b/doc/ioc/developer-guides/packaging-modules.md deleted file mode 100644 index ddecb6f1..00000000 --- a/doc/ioc/developer-guides/packaging-modules.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Packaging modules ---- - -TODO diff --git a/doc/ioc/developer-guides/packaging.md b/doc/ioc/developer-guides/packaging.md deleted file mode 100644 index b4f88a7a..00000000 --- a/doc/ioc/developer-guides/packaging.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Packaging new software ---- - -TODO diff --git a/doc/ioc/developer-tutorials.md b/doc/ioc/developer-tutorials.md deleted file mode 100644 index 13be9899..00000000 --- a/doc/ioc/developer-tutorials.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Developer Tutorials ---- - -This section of the documentation book contains tutorials[^1] for contributors to the EPNix project, related to building and deploying EPICS IOCs. - -[^1]: diff --git a/doc/ioc/explanations.md b/doc/ioc/explanations.md deleted file mode 100644 index 9642641c..00000000 --- a/doc/ioc/explanations.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Explanations ---- - -This section of the documentation book contains explanations[^1] of various concepts and patterns related to building and deploying EPICS IOCs with EPNix. - -[^1]: diff --git a/doc/ioc/faq.md b/doc/ioc/faq.md deleted file mode 100644 index 7d6b1b43..00000000 --- a/doc/ioc/faq.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Frequently Asked Questions ---- - -# I am getting weird Git errors about an unknown `-C` option - -You may be using a system with an old version of Git. -You may install a recent version of Git for your user by running `nix-env -iA nixpkgs.git`{.bash}. - -# A file I created isn't found when I run `nix build`{.bash} - -If your top is a Git repository, you must `git add`{.bash} those files to make them recognized by Nix. - -# An App can't find a build product from another App - -EPNix enables parallel builds by default. -These means that if App dependencies aren't specified, these Apps will compile in no particular order. -Use `_DEPEND_DIRS += `{.makefile} in your top-level `Makefile`. - -# How do I version a whole EPNix top? - -Meaning, not versioning an App separate from the top. -This might be justified if you don't intend to share an App in any other top. - -1. First, create a top and an App, as in the [StreamDevice tutorial]. - -2. Make sure to add an exception for the `exampleApp` folder at the end of the top's `.gitignore` file: - -``` ini -... -# Applications and Support modules should be an EPNix dependency in flake.nix -*App -*Sup -# You can add exceptions like this: -# --- -#!myCustomLocalApp -!exampleApp -``` - -3. Then, version both the top and the App: - -``` bash -git init -git add -N . -``` - -4. Finally, in your `flake.nix`, you can remove any input and value in `epnix.applications.apps` that refers to this directory. - - [StreamDevice tutorial]: ./tutorials/streamdevice.md diff --git a/doc/ioc/guides.md b/doc/ioc/guides.md deleted file mode 100644 index c023ea30..00000000 --- a/doc/ioc/guides.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: User guides ---- - -This section of the documentation book contains how-to guides[^1] for users of the EPNix project wanting to build EPICS IOCs. - -[^1]: diff --git a/doc/ioc/guides/developing-modules.md b/doc/ioc/guides/developing-modules.md deleted file mode 100644 index 79beb475..00000000 --- a/doc/ioc/guides/developing-modules.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Developing support modules ---- - -```{=html} - -``` -It can happen that one needs to hack on an EPICS support module, while also developing an App. -This might be to develop and test the support module, or to patch and test the support module, etc. - -This is where Nix's reproducibility guarantees might seem to be in the way: dependencies are taken from the `/nix/store` instead of your local repository. -You can add it as a flake input instead, but that requires to run `nix flake lock --update-input mySupport`{.bash} on each modification, etc. - -To bypass these constraints, there are several mechanisms that lets you to temporarily weaken these constraints for development purposes. - -# Packaging a starter module - -First, clone the EPNix repository, and package your support module. -You can look at the [Packaging modules] guide, this doesn't even have to compile yet, but you need to specify the dependencies of your support module. - - [Packaging modules]: ../developer-guides/packaging-modules.md - -# Hacking on your module - -From the directory containing the source code of your support module, run: - -``` bash -nix develop "/path/to/local/epnix#support/mySupport" -# Then, inside the development shell -dontUnpack=true -genericBuild -``` - -This will put the result of your compilation under `outputs/out`. -If you make modifications to your support module, run `buildPhase`{.bash} from the same development shell to recompile it. - -# Using it on your EPICS top - -Before trying to compile your top, make sure that your support module is included in the `support.modules` option of your EPNix top: - -``` nix -support.modules = with pkgs.epnix.support; [ mySupport ]; -``` - -Now that the support module is compiled and installed in a local directory, you can ask Nix to use it as is. -This can be done by running this command from your EPICS top directory: - -``` bash -nix develop \ - --override-input epnix '/path/to/local/epnix' \ - --redirect '/path/to/local/epnix#support/mySupport' '/path/to/mySupport/outputs/out' -# Then, normal hacking on an EPICS top... -``` - -The `--override-input` option instructs Nix to use your local EPNix fork instead of the one hosted on GitHub. -Use this option to override flake inputs. - -The `--redirect` option instructs Nix to use your local directory for your support module, instead of a module installed in the `/nix/store`. -Use this option to override individual packages. - ------------------------------------------------------------------------- - -With this setup, you can hack and compile your support module, and the changes will be directly visible to your top. -This enables you to hack on both project at the same time, each on their own development shell. - -One question one may ask: - -> What's the difference between running the complex `nix develop`{.bash} command and just putting `/path/to/mySupport/outputs/out` into `RELEASE.local`? - -One thing that the complex `nix develop`{.bash} command does correctly, is replacing *everything* that would have been `/nix/store/...-mySupport../` into your development shell. -This includes the `RELEASE.local` file, but this may not be the only thing: - -For example, if you're hacking on the `seq` support module, not only will it put the path to your local `seq` module into `RELEASE.local`, but it will also put some `seq` specific programs into your `$PATH`{.bash}, like the `snc`{.bash} utility. -These programs will be those from your local build, not the ones coming from the EPNix repository. diff --git a/doc/ioc/guides/flake-registry.md b/doc/ioc/guides/flake-registry.md deleted file mode 100644 index 23483acd..00000000 --- a/doc/ioc/guides/flake-registry.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Setting up the flake registry ---- - -While developing with EPNix, -it's possible you will end up typing `'github:epics-extensions/epnix'` quite often. - -It happens when you need to create a "top" template, -or when you just want to have `epics-base` in your shell, -and so on. - -This is tedious. - -Nix provides a way of shortening these URLs, -by adding to the [Nix registry][]: - -``` bash -nix registry add epnix 'github:epics-extensions/epnix' -``` - -Now, referring to `epnix` in Nix command-lines will be as if you referred to the full URL. -For example, the develop command to have EPICS based installed outside of a top would be: - -``` bash -nix develop epnix -``` - -If you want to initialize an EPNix top, -you can run: - -``` bash -nix flake new -t epnix my-top -``` - - [Nix registry]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-registry.html#description diff --git a/doc/ioc/guides/override-package.md b/doc/ioc/guides/override-package.md deleted file mode 100644 index 4609f0b2..00000000 --- a/doc/ioc/guides/override-package.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Override a support module ---- - -TODO diff --git a/doc/ioc/guides/pinning.md b/doc/ioc/guides/pinning.md deleted file mode 100644 index b2dc7175..00000000 --- a/doc/ioc/guides/pinning.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Pin the version of a Nix dependency ---- - -TODO diff --git a/doc/ioc/guides/private-repo-setup.md b/doc/ioc/guides/private-repo-setup.md deleted file mode 100644 index 685f3f9e..00000000 --- a/doc/ioc/guides/private-repo-setup.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Private repository setup ---- - -To avoid a great deal of confusion, it's best to configure your machine so that it can clone your private repositories unattended. -This means that this command should succeed without asking for user input on the terminal: - -``` bash -git clone 'ssh://git@your.gitlab.com/your/epicsApp.git' -``` - -But, asking for user input graphically is acceptable. - -The reason is that the Nix command-line tool often writes text on the terminal, and does so over the questions asked by programs like SSH or Git. -If SSH or Git asks for a password on the terminal, you probably won't see it, and confusion will follow when the Nix command hangs. - -There's two main ways to configure your machine for this: - -- SSH keys -- GitHub / GitLab tokens - -# SSH keys - -## Configuring the SSH key - -To setup SSH keys to use with your GitHub account, you can follow the [official documentation][github-ssh]. - -To setup SSH keys to use with your GitLab account, you can follow the [official documentation][gitlab-ssh], and particularly look at these sections: - -- See if you have an existing SSH key pair -- Generate an SSH key pair -- Add an SSH key to your GitLab account -- Verify that you can connect - - [github-ssh]: https://docs.github.com/en/authentication/connecting-to-github-with-ssh - [gitlab-ssh]: https://docs.gitlab.com/ee/user/ssh.html - -## Configuring the ssh-agent - -If you have a GNOME installation, chances are you already have an ssh-agent installed and running. - -To check, open a *new* terminal, and look at the value of the `$SSH_AUTH_SOCK`{.bash} variable. - -If it returns nothing, install `gnome-keyring`, then log out and log in again. - -Then, reopen a new terminal, and add your configured SSH key like so: - -``` bash -ssh-add 'path/to/key/id_ed25519' -``` - -Check that logging in to GitLab doesn't ask for user input on the terminal: - -``` bash -ssh -T 'git@your.gitlab.com' -# Welcome to GitLab, @user! -``` - -If it doesn't work, but you have `gnome-keyring-daemon` installed and running, -you can add this line to your `~/.bashrc`: - -``` bash -export SSH_AUTH_SOCK=/run/user/$UID/keyring/ssh -``` - -# GitHub / GitLab tokens - -GitHub and GitLab tokens offer a timed way of authenticating, suitable for either quick and dirty access, or for setting up services or scripts that need access to GitHub / GitLab repositories. -In any case, tokens shouldn't be used for usual development. - -In GitLab, you can create tokens either per-user, per-group, or per-project. - -In GitHub, you can only create personal access tokens, but their usage can be restricted in an organization. - -Creating a GitHub token, or a Gitlab token for your user means that you can give it access to all projects and APIs that you have access to. -This can be useful for your personal applications, or tools like [glab]. - -In GitLab, you can create a token for given group or project so that it offers access to that specific group or project. -These kinds of tokens should be preferred. - - [glab]: https://docs.gitlab.com/ee/integration/glab/ - -## GitHub - -To create a GitHub token, follow the [official documentation][github-token] - - [github-token]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token - -## GitLab - -```{=html} - -``` -To create a GitLab token, go to the user/group/project settings, under the "Access Tokens" section. -Give your token a meaningful name, an expiration date, and for a group/project, select the appropriate role. - -If you only want your token to be able to clone repositories, you can just select the `read_repository` scope. -Else refer to GitLab's official documentation by clicking "Learn more." - -After creating the personal access token, you can copy the token's value. -Be careful, as this value won't be accessible after closing the page. - -If you want to clone any repository, the URL will need to be: - -``` bash -https://gitlab-ci-token:${TOKEN}@your.gitlab.com" -``` - -As EPNix uses SSH flake inputs, you can use this command to instruct Git to rewrite GitLab URLs: - -``` bash -git config --global url."https://gitlab-ci-token:${TOKEN}@your.gitlab.com".insteadOf "ssh://git@your.gitlab.com" -``` - -To check that your setup is working, run the following command: - -``` bash -git clone 'ssh://git@your.gitlab.com/your/epicsApp.git' -``` diff --git a/doc/ioc/guides/testing.md b/doc/ioc/guides/testing.md deleted file mode 100644 index dadc5790..00000000 --- a/doc/ioc/guides/testing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Testing ---- - -TODO diff --git a/doc/ioc/guides/testing/packaging-python-scripts.md b/doc/ioc/guides/testing/packaging-python-scripts.md deleted file mode 100644 index 2bd5d2d1..00000000 --- a/doc/ioc/guides/testing/packaging-python-scripts.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Packaging Python scripts ---- - -```{=html} - -``` -As EPNix uses Nix, you can package Python scripts as helpers for your integration tests, by using the provided [infrastructure] of nixpkgs. -In fact, you can package any program in any language, but this document focuses on Python scripts with [Poetry] for their simplicity and popularity. - - [infrastructure]: https://nixos.org/manual/nixpkgs/stable/#python - [Poetry]: https://python-poetry.org/ - -# Getting started - -We recommend using the Poetry package in your EPNix environment, through Nix, to use the same version as the one building the Python script. - -You can do this by adding this bit in your `flake.nix` file: - -``` nix -epnix.devShell.packages = [ - { package = pkg.poetry; category = "development tools"; } -]; -``` - -Next, you can start your development shell with `nix develop`, go to the directory of your test, and create a new project with the command: - -``` bash -poetry new -``` - -This will create a Python project under the `` directory. -Under it, you will find a `pyproject.toml` where you can specify the dependencies of your script. -For example, you can specify `modbus` to add the Python [modbus package], if you want to test modbus communication. -You can remove the dependency on pytest if won't add unit tests to your Python script. - -To add an entry point to your Python code, you can use the `tool.poetry.scripts` section like so: - -``` toml -[tool.poetry.scripts] -my_python_script = "my_python_script:main" -``` - -This will add an executable named `my_python_script`{.bash} that will run the `main()`{.python} function of the `my_python_script`{.python} module. - -For more information on how to use poetry, please refer to the [Poetry documentation]. - -Before packaging this script using Nix, it's important to generate the lock file, and to remember to re-generate it each time you change the `pyproject.toml` file. - -You can do this with the following command: - -``` bash -poetry lock -``` - -Then, in your [integration test] file, you can package it like this: - -``` nix -{ build, pkgs, ... }: - -let - pythonScript = pkgs.poetry2nix.mkPoetryApplication { - projectDir = ./path/to/my-python-script; - }; -in -pkgs.nixosTest { - name = "myTest"; - - # ... -} -``` - -With this, you can use the `pythonScript` variable as you see fit. - - [modbus package]: https://pypi.org/project/modbus/ - [Poetry documentation]: https://python-poetry.org/docs/basic-usage/ - [integration test]: ../../tutorials/integration-tests.md - -# Example usage: As a one shot test script - -Using a packaged Python script instead of the provided `testScript` has several advantages. -It can use dependencies provided by the community (like `modbus`, `systemd`, etc.), and you can make it run on the running virtual machine. - -Python script: - -``` python -import subprocess - -from modbus.client import * - - -def main(): - c = client(host='HOSTNAME') - modbus_values = c.read(FC=3, ADR=10, LEN=8) - - for i in range(8): - epics_value = subprocess.run( - ["caget", "-t", "MyPV:" + i], - capture_output=True, - ).stdout.strip() - - assert modbus_values[i] == int(epics_value), "Wrong value provided by epics" -``` - -Nix test: - -``` nix -{ build, pkgs, ... }: - -let - pythonScript = pkgs.poetry2nix.mkPoetryApplication { - projectDir = ./path/to/my-python-script; - }; -in -pkgs.nixosTest { - name = "myTest"; - - machine = { - environment.systemPackages = [ pythonScript ]; - - # ... - }; - - testScript = '' - # ... - - my_python_script --my-flag --my-option=3 - - # ... - ''; -} -``` - -# Example usage: As a systemd service - -Using a Python script as a systemd service is useful for mocking devices. -For more information, please see the [Creating a mocking server] guide. - -Python script: - -``` python -import logging -from logging import info - - -def main(): - logging.basicConfig(level=logging.INFO) - - while True: - info("doing things") - - # ... -``` - -Nix test: - -``` nix -{ build, pkgs, ... }: - -let - pythonScript = pkgs.poetry2nix.mkPoetryApplication { - projectDir = ./path/to/my-python-script; - }; -in -pkgs.nixosTest { - name = "myTest"; - - machine = { - systemd.services."my-python-service" = { - wantedBy = [ "multi-user.target" ]; - - serviceConfig.ExecStart = "${pythonScript}/bin/my_python_script"; - }; - - # ... - }; - - testScript = '' - # ... - - machine.wait_for_unit("my-python-service.service") - - # ... - ''; -} -``` - - [Creating a mocking server]: ../../tutorials/creating-a-mock-server.md diff --git a/doc/ioc/guides/testing/unit-tests.md b/doc/ioc/guides/testing/unit-tests.md deleted file mode 100644 index b5d0032f..00000000 --- a/doc/ioc/guides/testing/unit-tests.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Writing unit tests ---- - -# EPICS unit tests primer - -TODO - -# EPICS unit test API - -# Example diff --git a/doc/ioc/introduction.md b/doc/ioc/introduction.md deleted file mode 100644 index 1da2c047..00000000 --- a/doc/ioc/introduction.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: EPICS IOCs ---- - -# Introduction - -EPNix (pronunciation: like you are high on mushrooms) provides a way of building and packaging EPICS IOCs using the [Nix] package manager. - -By leveraging the Nix package manager, it provides several advantages compared to packaging EPICS the traditional way: - -Reproducibility: -: Your development environment is the same as your coworker's development environment, which is the same as your production environment. - -Complete dependencies: -: Your EPICS IOCs ship with the complete set of dependencies, which means you can to deploy your IOC without needing to install any dependency on the target machine (except for Nix itself). - -Dependency traceability: -: The version of your dependencies are locked, updated manually, and traced in your `flake.lock` file. - Combined with code versioning, you can build your project with the same environment years later, and you can roll back to any earlier version. - -Development shell: -: Provides you with a set of tools adapted to your project, no matter what you have installed on your machine. - -Declarative configuration: -: Define what you want in your IOC in a declarative and extendable manner. - -Integration tests: -: Write tests using Python, by starting a virtual machine with your IOC running. - - [Nix]: https://nixos.org/guides/how-nix-works.html - -## Packaging policy - -To be able to specify your dependencies in your EPNix configuration, EPNix provides a package repository, packaging for example `epics-base`, `asyn`, `StreamDevice`, etc. - -In its package repository, EPNix officially supports the latest upstream version. - -However, since Nix "locks" your dependencies, this means you don't need to upgrade your dependencies if you don't want to. -What this means in practice: your IOC repository uses the EPNix project repository at a fixed commit, like using a repository at a fixed point in time. -Nix records this commit SHA in the `flake.lock` file, which should be checked out in your Git repository. - -### The epics-base package - -The epics-base package has no significant modification compared to the upstream version at [Launchpad]. -One goal of EPNix is to keep those modifications to a minimum, and upstream what's possible. - - [Launchpad]: https://git.launchpad.net/epics-base diff --git a/doc/ioc/references.md b/doc/ioc/references.md deleted file mode 100644 index cb56d640..00000000 --- a/doc/ioc/references.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: References ---- - -This section of the book contains reference documentation[^1] related to building and deploying EPICS IOCs with EPNix. - -[^1]: diff --git a/doc/ioc/tutorials.md b/doc/ioc/tutorials.md deleted file mode 100644 index 39c569ff..00000000 --- a/doc/ioc/tutorials.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: User tutorials ---- - -Tutorials[^1] for users of the EPNix project wanting to build and deploy EPICS IOCs. - -[^1]: diff --git a/doc/ioc/tutorials/adding-options.md b/doc/ioc/tutorials/adding-options.md deleted file mode 100644 index 60cbc4d8..00000000 --- a/doc/ioc/tutorials/adding-options.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adding configuration options ---- - -TODO diff --git a/doc/ioc/tutorials/creating-a-mock-server.md b/doc/ioc/tutorials/creating-a-mock-server.md deleted file mode 100644 index 0bdc9738..00000000 --- a/doc/ioc/tutorials/creating-a-mock-server.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Creating a mocking server ---- - -TODO diff --git a/doc/ioc/tutorials/day-to-day-dev.md b/doc/ioc/tutorials/day-to-day-dev.md deleted file mode 100644 index d1417baf..00000000 --- a/doc/ioc/tutorials/day-to-day-dev.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Day to day development ---- - -TODO diff --git a/doc/ioc/tutorials/integration-tests.md b/doc/ioc/tutorials/integration-tests.md deleted file mode 100644 index 0db48a66..00000000 --- a/doc/ioc/tutorials/integration-tests.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Integration tests ---- - -# Writing the test - -Through the [NixOS testing framework], EPNix provides a way of specifying a machine configuration, and running a Python script that can do various kind of testing. - -If you created your IOC using the EPNix template, like suggested in the [StreamDevice tutorial], you will see a `checks/` directory. -This directory should contain the integration tests you want to run. - -To add an integration test to EPNix, record it in your `flake.nix` under the `epnix.checks.files` option. - -For example, in the EPNix template, you will see in your `flake.nix` file: - -``` nix -checks.files = [ ./checks/simple.nix ]; -``` - -The `./checks/.nix` file should contain a NixOS test like so: - -``` nix -{ build, pkgs, ... }: - -pkgs.nixosTest { - name = "myTest"; - - machine = { - # Description of the NixOS machine... - }; - - testScript = '' - # Python script that does the testing... - ''; -} -``` - -This test will create a NixOS virtual machine from the given configuration, and run the test script. -Note that the test script does *not* run on the virtual machine, but communicates with it. -This is because the test script can start, shut down, or reboot the machine, and also because NixOS tests can also manage several virtual machines, not just one. - -For an overview of what you can input in the machine configuration, please refer to the [NixOS documentation]. -You can also read about the Python test script API [here][NixOS testing framework]. - - [NixOS testing framework]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests - [StreamDevice tutorial]: ./streamdevice.md - [NixOS documentation]: https://nixos.org/manual/nixos/stable/index.html#sec-configuration-syntax - -# Starting your IOC through systemd - -We recommend starting your IOC through a systemd service, which you can describe in Nix like so: - - - -``` nix -# Inside the `machine` attribute -{ - systemd.services.my-ioc = { - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${build}/iocBoot/iocexample/st.cmd"; - WorkingDirectory = "${build}/iocBoot/iocexample"; - - # Makes the EPICS command-line not quit for 100 seconds, if it doesn't - # receive anything on the standard input - StandardInputText = "epicsThreadSleep(100)"; - }; - }; - - # Provides the caget / caput / etc. commands to the test script - environment.systemPackages = [ pkgs.epnix.epics-base ]; -} -``` - -You can view the list of options available for a NixOS machine [here]. - -Then, you can write your test script. -Note that the test script doesn't run directly on the machine, but communicates with the machine through the `machine` variable. - -An example of a testing script: - -``` python -start_all() - -machine.wait_for_unit("default.target") -machine.wait_for_unit("my-ioc.service") - -machine.wait_until_succeeds("caget stringin") -machine.wait_until_succeeds("caget stringout") -machine.fail("caget non-existing") - -with subtest("testing stringout"): - def test_stringout(_) -> bool: - machine.succeed("caput stringout 'hello'") - status, _output = machine.execute("caget -t stringout | grep -qxF 'hello'") - - return status == 0 - - retry(test_stringout) - - assert "hello" not in machine.succeed("caget -t stringin") -``` - -Note that the script extensively uses the `wait_until_succeeds` method and the `retry` function. -This is because EPICS has few guarantees about whether it propagates changes immediately, and so it's better to encourage the use of retries, instead of hoping the timing lines up. - -If you would like to use a fully fledged python script on the machine, which can use Python dependencies like pyepics, please refer to the guide [Packaging Python scripts]. - -You can find methods available on the `machine` variable and other particularities in the [NixOS tests documentation]. - -You can also look at examples either in the EPNix repository under the [`checks` folder], or in nixpkgs under the [`nixos/tests` folder]. - -```{=html} - -``` - - [here]: https://search.nixos.org/options?channel=21.11&from=0&size=50&sort=alpha_asc&type=packages&query=systemd.services. - [Packaging Python scripts]: ../guides/testing/packaging-python-scripts.md - [NixOS tests documentation]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests - [`checks` folder]: https://github.com/epics-extensions/epnix/tree/master/checks - [`nixos/tests` folder]: https://github.com/NixOS/nixpkgs/tree/master/nixos/tests diff --git a/doc/ioc/tutorials/porting.md b/doc/ioc/tutorials/porting.md deleted file mode 100644 index d25efef1..00000000 --- a/doc/ioc/tutorials/porting.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Porting IOCs to EPNix ---- - -TODO diff --git a/doc/ioc/tutorials/pre-requisites.md b/doc/ioc/tutorials/pre-requisites.md deleted file mode 100644 index 6ea7a9dd..00000000 --- a/doc/ioc/tutorials/pre-requisites.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Pre-requisites" ---- - -The requirements for using EPNix are having curl, Nix, and Git installed, -either in a Linux system, -or in Windows' WSL2. -Nix must be configured with "flakes" enabled. - -You *don't* need to have EPICS base installed globally, -EPNix makes it available to you -when you enter your top's development shell. - -Having a global EPICS base installation shouldn't pose any issue. - -# Installing Nix - -::: callout-warning -If you use a Linux distribution with SELinux, -be sure to turn it off. -You can do this by adding the line `SELINUX=disabled` in `/etc/sysconfig/selinux` on distributions based on RedHat Enterprise Linux (RHEL) like CentOS, Rocky Linux, and so on. -::: - -If you don't have Nix installed, -first follow the [official instructions]. -Make sure to have the `xz` utility installed beforehand, -often part of the `xzip` or `xz` package. - -Unless you use WSL2, -use the multi-user installation, -because it builds packages in an isolated environment. - - [official instructions]: https://nixos.org/download.html#download-nix - -# Enabling Nix flakes and the `nix`{.bash} command - -Because Nix flakes and the unified `nix` command are experimental features at the time of writing, -you need to enable them in your `/etc/nix/nix.conf`. - -To enable this feature, -add this line to your `/etc/nix/nix.conf`: - -``` ini -experimental-features = nix-command flakes -``` - -If you have installed Nix in multi-user mode, -then you have to restart the Nix daemon by running: - -``` bash -systemctl restart nix-daemon.service -``` - -# Untracked files and Nix flakes - -One important thing with Nix flakes: -when your flake is in a Git repository, -Nix only considers files that Git tracks. - -For example, -if your `flake.nix` is in a Git repository, -and you create a file `foobar.txt`, -you must run `git add [-N] foobar.txt`{.bash} to make Nix recognize it. - -This prevents copying build products into the Nix store. - -# Git version - -If you use an old system and see Git errors when using Nix, -install a recent version of Git by running this: - -``` bash -nix-env -iA nixpkgs.git -``` - -This command installs a recent version of Git for your current user. diff --git a/doc/ioc/tutorials/streamdevice.md b/doc/ioc/tutorials/streamdevice.md deleted file mode 100644 index 29441736..00000000 --- a/doc/ioc/tutorials/streamdevice.md +++ /dev/null @@ -1,294 +0,0 @@ ---- -title: "Creating a StreamDevice IOC" ---- - -In this tutorial, -you're gonna learn how to create an EPICS IOC with EPNix -that communicates with a power supply, -using the [StreamDevice] support module. - - [StreamDevice]: https://paulscherrerinstitute.github.io/StreamDevice/ - -# Pre-requisites - -Verify that you have all pre-requisites installed. -If not, -follow the [Pre-requisites] section. - - [Pre-requisites]: ./pre-requisites.md - -# Running the power supply simulator - -EPNix has a power supply simulator -for you to test your IOC. - -To run it: - -``` bash -nix run 'github:epics-extensions/epnix#psu-simulator' -``` - -For the rest of the tutorial, -leave it running in a separate terminal. - -# Creating your top - -We can use these command to create an EPNix top: - -``` bash -# Initialise an EPNix top -nix flake new -t 'github:epics-extensions/epnix' my-top -cd my-top - -# Enter the EPNix development shell, that has EPICS base installed in it. -nix develop - -# Create your app and ioc boot folder -makeBaseApp.pl -t ioc example -makeBaseApp.pl -i -t ioc -p example -a linux-x86_64 Example - -# Create a git repository, and make sure all files are tracked -git init -git add . -``` - -After that, -you can already check that your top build with: - -``` bash -nix build -L -``` - -This `nix build`{.sh} command compiles your IOC, -and all its dependencies. -This makes the usual EPICS environment setup unneeded. - -If found in the official Nix cache server, -Nix downloads packages from there -instead of compiling them. - -This command puts a `./result` symbolic link in your current directory, -containing the compilation result. - -# Adding StreamDevice to the EPNix environment - -Adding dependencies to the EPNix environment happen inside the `flake.nix` file. -This file is the main entry point for specifying your build environment: -most Nix commands used here read this file to work. - -For adding StreamDevice, -change yours like so: - -``` {.diff filename="flake.nix"} - # Add one of the supported modules here: - # --- -- #support.modules = with pkgs.epnix.support; [ StreamDevice ]; -+ support.modules = with pkgs.epnix.support; [ StreamDevice ]; -``` - -Then, -leave your EPNix development shell by running `exit`{.sh}, -and re-enter it with `nix develop`{.sh}. - -Because you modified the support modules, -run `eregen-config`{.sh} to regenerate `configure/RELEASE.local`. - -With this, -your development shell has StreamDevice available, -and StreamDevice is also added in the `RELEASE.local` file. - -::: callout-tip -As a rule, -each time you edit the `flake.nix` file, -leave and re-enter your development shell (`exit`{.sh} then `nix develop`{.sh}), -and run `eregen-config`{.sh}. -::: - -# Adding StreamDevice to your EPICS app - -To add StreamDevice to your app, -make the following modifications: - -Change the `exampleApp/src/Makefile` -so that your App knows the record types of StreamDevice and its dependencies. -Also change that file so that it links to the StreamDevice library and its dependencies, -during compilation. -For example: - -``` {.makefile filename="exampleApp/src/Makefile"} -# ... - -# Include dbd files from all support applications: -example_DBD += calc.dbd -example_DBD += asyn.dbd -example_DBD += stream.dbd -example_DBD += drvAsynIPPort.dbd - -# Add all the support libraries needed by this IOC -example_LIBS += calc -example_LIBS += asyn -example_LIBS += stream - -# ... -``` - -Create the `exampleApp/Db/example.proto` file -that has the definition of the protocol. -This file tells StreamDevice what to send the power supply, -and what to expect in return. - -``` {.perl filename="exampleApp/Db/example.proto"} -Terminator = LF; - -getVoltage { - out ":VOLT?"; in "%f"; -} - -setVoltage { - out ":VOLT %f"; - @init { getVoltage; } -} -``` - -Create the `exampleApp/Db/example.db` file. -That file specifies the name, type, and properties of the Process Variables (PV) -that EPICS exposes over the network. -It also specifies how they relate to the functions written in the protocol file. - -``` {.perl filename="exampleApp/Db/example.db"} -record(ai, "${PREFIX}VOLT-RB") { - field(DTYP, "stream") - field(INP, "@example.proto getVoltage ${PORT}") -} - -record(ao, "${PREFIX}VOLT") { - field(DTYP, "stream") - field(OUT, "@example.proto setVoltage ${PORT}") -} -``` - -Change `exampleApp/Db/Makefile` -so that the EPICS build system installs `example.proto` and `example.db`: - -``` {.makefile filename="exampleApp/Db/Makefile"} -# ... - -#---------------------------------------------------- -# Create and install (or just install) into /db -# databases, templates, substitutions like this -DB += example.db -DB += example.proto - -# ... -``` - -Change your `st.cmd` file -so that it knows where to load the protocol file, -and how to connect to the remote power supply. - -``` {.csh filename="iocBoot/iocExample/st.cmd"} -#!../../bin/linux-x86_64/example - -< envPaths - -## Register all support components -dbLoadDatabase("${TOP}/dbd/example.dbd") -example_registerRecordDeviceDriver(pdbbase) - -# Where to find the protocol files -epicsEnvSet("STREAM_PROTOCOL_PATH", "${TOP}/db") -# The TCP/IP address of the power supply -drvAsynIPPortConfigure("PS1", "localhost:8727") - -## Load record instances -dbLoadRecords("${TOP}/db/example.db", "PREFIX=, PORT=PS1") - -iocInit() -``` - -And run `chmod +x iocBoot/iocExample/st.cmd` -so that you can run your command file as-is. - -You can test that your top builds by running: - -``` bash -nix build -L -``` - -You will see that your IOC does not build. -This is because we haven't told Git to track those newly added files, -and so Nix ignores them too. - -Run `git add .`{.sh} for Git and Nix to track all files, -and try a `nix build -L`{.sh} again. - -If everything goes right, -you can examine your compiled top under `./result`. - -You can observe that: - -- the `example` app is installed under `bin/` and `bin/linux-x86_64`, - and links to the correct libraries -- `example.proto` and `example.db` are installed under `db/` -- `example.dbd` is generated and installed under `dbd/` - -# Running your IOC - -To run your IOC, -build it first with `nix build -L`{.sh}, -and change directory into the `./result/iocBoot/iocExample` folder. -Then, run: - -``` bash -./st.cmd -``` - -You should see the IOC starting and connecting to `localhost:8727`. - -# Recompiling with make - -Using `nix build`{.sh} to compile your IOC each time might feel slow. -This is because Nix re-compiles your IOC from scratch each time. - -If you want a more "traditional" edit / compile / run workflow, -you can place yourself in the development shell with `nix develop`{.sh}, -and use `make` from here. - -# Next steps - -More commands are available in the power supply simulator. -To view them, -close your IOC, -and open a direct connection to the simulator: - -``` bash -nc localhost 8727 -# or -telnet localhost 8727 -``` - -You can install the `nc` command through the `netcat` package, -or you can install the `telnet` command through the `telnet` package, - -Either command opens a prompt -where you can type `help` then press enter -to view the available commands. - -Try to edit the protocol file and the database file -to add those features to your IOC. - -For more information about how to write the StreamDevice protocol, -have a look at the [Protocol Files] documentation. - -You might also be interested in reading [Setting up the flake registry] - - [Protocol Files]: https://paulscherrerinstitute.github.io/StreamDevice/protocol.html - [Setting up the flake registry]: ../guides/flake-registry.md - -# Pitfalls - -Although EPNix tries to be close to a standard EPICS development, -some differences might lead to confusion. -You can find more information about this in the [FAQ]. - - [FAQ]: ../faq.md diff --git a/doc/logo.svg b/doc/logo.svg deleted file mode 100644 index fe9f751c..00000000 --- a/doc/logo.svg +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/doc/nixos/guides/_pre-requisites.md b/doc/nixos/guides/_pre-requisites.md deleted file mode 100644 index d13fe83a..00000000 --- a/doc/nixos/guides/_pre-requisites.md +++ /dev/null @@ -1,41 +0,0 @@ -# Pre-requisites - -- Having a NixOS machine with a flake configuration. - -If you're not sure how to do this, -you can follow the [Archiver Appliance tutorial], -which is a good introduction on how to make a NixOS VM. - -If you have such a configuration, -make sure that: - -- You have the `epnix` flake input -- You have added `epnix` as an argument to your flake outputs -- You have imported EPNix' NixOS module - -For example: - -``` {.diff filename="flake.nix"} - { - # ... - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; -+ inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; - - # ... - outputs = { - self, - nixpkgs, -+ epnix, - }: { - nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { - modules = [ -+ epnix.nixosModules.nixos - - # ... - ]; - }; - }; - } -``` - - [Archiver Appliance tutorial]: ../tutorials/archiver-appliance.md diff --git a/doc/nixos/guides/ca-gateway.md b/doc/nixos/guides/ca-gateway.md deleted file mode 100644 index ede4ea15..00000000 --- a/doc/nixos/guides/ca-gateway.md +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Channel Access gateway setup ---- - -The Channel Access (CA) gateway is a program -that acts as gateway, -which enables client from a network to access IOCs on another network. - -Setting up a CA gateway also enables you -to add extra access security rules on top of IOCs. - -For more details and documentation about the CA PV gateway, -you can examine the [gateway main page]. - - [gateway main page]: https://epics.anl.gov/extensions/gateway/ - -{{< include _pre-requisites.md >}} - -# Enabling the gateway - -To enable the gateway, -add this to your configuration: - -``` nix -{ - services.ca-gateway = { - enable = true; - openFirewall = true; - }; -} -``` - -This configuration starts the CA gateway in a `ca-gateway.service` systemd service. -In this configuration, -the gateway listens on all interface with a broadcast IP address, -and forwards all Channel Access request. - -The `openFirewall` option opens the -5064 TCP, -5064 UDP, -and 5065 UDP ports on all network interfaces. - -# Firewall on specific interfaces - -If you want to enable the firewall on specific interfaces, -you can remove the `openFirewall` option -and configure the firewall manually. - -You can also use the `cip` setting -to specify where the gateway should listen -for the CA server part. - -For example: - -``` nix -{config, ...}: { - services.ca-gateway = { - enable = true; - # Server side listen address - # Let's say this IP address is on enp0s2 - settings.sip = ["10.0.2.1"]; - - # Let's also say the enp0s1 interface is - # where communication with "real" IOCs happen (client side) - - # openFirewall is left as false by default - }; - - networking.firewall = let - gwSettings = config.services.ca-gateway.settings; - in { - interfaces = { - # Open the firewall on the interface from the client side of the gateway, - # this will be the side of the gateway listening - # for replies to beacons and PV search requests - "enp0s1".allowedUDPPorts = [5065]; - - # Open the firewall on the interface from the server side of the gateway, - # this will be the side of the gateway listening for Channel Access requests - "enp0s2" = { - # Use the value of the `sport` setting - allowedTCPPorts = [gwSettings.sport]; - allowedUDPPorts = [gwSettings.sport]; - }; - }; - - # Allow incoming UDP packets with *source* port 5064, - # from the client side of the gateway. - # This is needed to listen to CA broadcast responses - extraCommands = '' - ip46tables -A nixos-fw -p udp --sport 5064 -j nixos-fw-accept -i enp0s1 - ''; - }; -} -``` - -# Filtering IOCs - -By using the `cip` setting, -you can filter which IOCs get exposed by the gateway. -This is equivalent to setting the environment variable `EPICS_CA_ADDR_LIST` -and setting `EPICS_CA_AUTO_ADDR_LIST=NO`. - -For example: - -``` nix -{ - services.ca-gateway = { - enable = true; - # These IOCs get exposed by the gateway - settings.cip = [ - "10.0.1.42" - "10.0.1.69" - - # you can specify the port, too, - # if your IOC listens on something other than 5064 - "10.0.1.237:5067" - - # domain names also work - "myioc" - ]; - }; -} -``` - -# Filtering process variables - -By using the `pvlist` setting, -you can filter which PVs get exposed by the gateway. - -This option takes a file in the gateway `pvlist` format. -See the [`GATEWAY.pvlist`] example on the ca-gateway repository. -The list supports regular expressions (Perl style). - - [`GATEWAY.pvlist`]: https://github.com/epics-extensions/ca-gateway/blob/master/example/GATEWAY.pvlist - -## In the configuration - -For example: - -``` nix -{pkgs, ...}: { - services.ca-gateway = { - enable = true; - # These PVs get exposed by the gateway - # This list implements an "allowlist": - # DENY by default, some PVs explicitely ALLOW - settings.pvlist = pkgs.writeText "gateway.pvlist" '' - EVALUATION ORDER DENY, ALLOW - - .* DENY - - MY_PV1 ALLOW - MY_PV2 ALLOW - - # Or: - - MY_PV[0-9]+ ALLOW - ''; - }; -} -``` - -## In a separate file - -For long lists, -it can be better -to put it in a separate file. -You can do this -by adding a `gateway.pvlist` in the same directory as your configuration: - -``` {.perl filename="gateway.pvlist"} -EVALUATION ORDER DENY, ALLOW - -.* DENY - -MY_PV1 ALLOW -MY_PV2 ALLOW - -# Or: - -MY_PV[0-9]+ ALLOW -``` - -And in your configuration: - -``` nix -{ - services.ca-gateway = { - enable = true; - # Make sure that the value is *not* quoted - settings.pvlist = ./gateway.pvlist; - }; -} -``` diff --git a/doc/nixos/guides/phoebus-alarm.md b/doc/nixos/guides/phoebus-alarm.md deleted file mode 100644 index 6c941b50..00000000 --- a/doc/nixos/guides/phoebus-alarm.md +++ /dev/null @@ -1,214 +0,0 @@ ---- -title: Phoebus Alarm single server setup ---- - -The Phoebus Alarm collection of services enables monitoring EPICS PVs, -and report alarms in a server. -Phoebus clients can then contact this server, -to see a list of current alarms, earlier alarms, and so on. - -This guide focuses on installing and configuring these services on a single server. - -For more information about these services, -examine the official documentation: - -- [Service Architecture] -- [Alarm Server] -- [the README of Alarm Server] for reference only, don't follow this guide on NixOS -- [Alarm Logging Service] - -The Phoebus Alarm Logging Service can also be called the Phoebus Alarm Logger. - - [Service Architecture]: https://control-system-studio.readthedocs.io/en/latest/services_architecture.html - [Alarm Server]: https://control-system-studio.readthedocs.io/en/latest/services/alarm-server/doc/index.html - [the README of Alarm Server]: https://github.com/ControlSystemStudio/phoebus/blob/master/app/alarm/Readme.md - [Alarm Logging Service]: https://control-system-studio.readthedocs.io/en/latest/services/alarm-logger/doc/index.html - -{{< include _pre-requisites.md >}} - -# Single server Phoebus Alarm setup - -To configure Phoebus Alarm, Phoebus Alarm Logger, Apache Kafka, and ElasticSearch on a single server, -add this to your configuration, -while taking care of replacing the IP address -and Kafka's `clusterId`: - -``` nix -{lib, pkgs, ...}: let - # Replace this with your machine's external IP address - # or DNS domain name - ip = "192.168.1.42"; - kafkaListenSockAddr = "${ip}:9092"; - kafkaControllerListenSockAddr = "${ip}:9093"; -in { - # The Phoebus Alarm server also automatically enables the Phoebus Alarm Logger - services.phoebus-alarm-server = { - enable = true; - openFirewall = true; - settings."org.phoebus.applications.alarm/server" = kafkaListenSockAddr; - }; - - services.phoebus-alarm-logger.settings."bootstrap.servers" = kafkaListenSockAddr; - - # Single-server Kafka setup - services.apache-kafka = { - enable = true; - # Replace with a randomly generated uuid. You can get one by running: - # nix shell 'nixpkgs#apacheKafka' -c kafka-storage.sh random-uuid - clusterId = "xxxxxxxxxxxxxxxxxxxxxx"; - formatLogDirs = true; - settings = { - listeners = [ - "PLAINTEXT://${kafkaListenSockAddr}" - "CONTROLLER://${kafkaControllerListenSockAddr}" - ]; - # Adapt depending on your security constraints - "listener.security.protocol.map" = [ - "PLAINTEXT:PLAINTEXT" - "CONTROLLER:PLAINTEXT" - ]; - "controller.quorum.voters" = [ - "1@${kafkaControllerListenSockAddr}" - ]; - "controller.listener.names" = ["CONTROLLER"]; - - "node.id" = 1; - "process.roles" = ["broker" "controller"]; - - "log.dirs" = ["/var/lib/apache-kafka"]; - "offsets.topic.replication.factor" = 1; - "transaction.state.log.replication.factor" = 1; - "transaction.state.log.min.isr" = 1; - }; - }; - - systemd.services.apache-kafka.unitConfig.StateDirectory = "apache-kafka"; - - # Open kafka to the outside world - networking.firewall.allowedTCPPorts = [9092]; - - services.elasticsearch = { - enable = true; - package = pkgs.elasticsearch7; - }; - - # Elasticsearch, needed by Phoebus Alarm Logger, is not free software (SSPL | Elastic License). - # To accept the license, add the code below: - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) [ - "elasticsearch" - ]; -} -``` - -From the Phoebus graphical client side, -add this configuration: - -``` ini -# For the Phoebus Alarm Server: -# Replace the IP address with your server's IP address or DNS domain name -org.phoebus.applications.alarm/server=192.168.1.42:9092 - -# For the Phoebus Alarm Logger: -# Replace the IP address again -org.phoebus.applications.alarm.logging.ui/service_uri=http://192.168.1.42:8080 -``` - -# Configuring topics - -The Phoebus Alarm system uses "topics" as a way of grouping alarms. -These topics are the available roots of your alarm tree. -You need to synchronize the topic names between: - -- Phoebus Alarm Server -- Phoebus Alarm Logger -- Phoebus graphical clients - -Changing the topic names in the Phoebus Alarm Server NixOS modules automatically creates them. - -::: callout-warning -Currently, the Phoebus Alarm Server doesn't support several topics. -::: - -For example, -if you want to have the topic `Project`, -add this configuration to the server: - -``` nix -{config, lib, ...}: let - topics = ["Project"]; -in { - services.phoebus-alarm-server = { - # ... - settings = { - # ... - "org.phoebus.applications.alarm/config_names" = topics; - }; - }; - - services.phoebus-alarm-logger.settings.alarm_topics = topics; -} -``` - -For the Phoebus graphical client, -add this configuration: - -``` ini -# config_name is only used in the Phoebus graphical client -org.phoebus.applications.alarm/config_name = Project -org.phoebus.applications.alarm/config_names = Project -``` - -# Configuring the address list - -If you want to limit the IOCs reachable by the Phoebus Alarm Server, -use these option: - -``` nix -{ - services.phoebus-alarm-server = { - # ... - settings = { - # ... - - # The Phoebus Alarm Server will only have access to these IOCs - "org.phoebus.pv.ca/addr_list" = ["192.168.1.5" "192.168.1.42"]; - "org.phoebus.pv.ca/auto_addr_list" = false; - }; - }; -} -``` - -# Configuring email support - -To enable email support, -set the `org.phoebus.email/mailport` setting. -Here is a list of options you might want to set: - -``` nix -{ - services.phoebus-alarm-server = { - # ... - settings = { - # ... - - "org.phoebus.email/mailhost" = "smtp.my-company.org"; - - # Optional: - - # 25 for plain SMTP - "org.phoebus.email/mailport" = 25; - # If authentication is needed: - "org.phoebus.email/username" = "user"; - "org.phoebus.email/password" = "password"; - # Default address to be used for From: - # if unspecified, then the last used "from" address is used - "org.phoebus.email/from" = "Sender "; - }; - }; -} -``` - -::: callout-warning -Currently, Phoebus Alarm Server only supports plain SMTP. -::: diff --git a/doc/nixos/guides/phoebus-save-and-restore.md b/doc/nixos/guides/phoebus-save-and-restore.md deleted file mode 100644 index f9a264f4..00000000 --- a/doc/nixos/guides/phoebus-save-and-restore.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Phoebus Save-and-restore setup ---- - -The Phoebus Save-and-restore service is used by clients -to manage configuration and snapshots of PV values. -These snapshots can then be used by clients for comparison or for restoring PVs. - -This guide focuses on installing and configuring the Save-and-Restore service on a single server. - -For more details and documentation about Phoebus Save-and-Restore, -you can examine the [Save-and-restore official documentation]. - - [Save-and-restore official documentation]: https://control-system-studio.readthedocs.io/en/latest/services/save-and-restore/doc/index.html - -{{< include _pre-requisites.md >}} - -# Enabling the Phoebus Save-and-restore service - -To enable the Phoebus Save-and-restore service, -add this to your configuration: - -``` nix -{lib, ...}: { - services.phoebus-save-and-restore = { - enable = true; - openFirewall = true; - }; - - # Elasticsearch, needed by Phoebus Save-and-restore, is not free software (SSPL | Elastic License). - # To accept the license, add the code below: - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) [ - "elasticsearch" - ]; -} -``` - -From the Phoebus graphical client side, -add this configuration - -``` ini -# Replace the IP address with your server's IP address or domain name -org.phoebus.applications.saveandrestore/jmasar.service.url=http://192.168.1.42:8080 -``` - -::: callout-warning -URLs for future versions of Phoebus Save-and-restore will need to change to: -`http://192.168.1.42:8080/save-restore` -::: diff --git a/doc/nixos/introduction.md b/doc/nixos/introduction.md deleted file mode 100644 index ddc9d0a0..00000000 --- a/doc/nixos/introduction.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: NixOS ---- - -# Introduction diff --git a/doc/nixos/tutorials/archiver-appliance.md b/doc/nixos/tutorials/archiver-appliance.md deleted file mode 100644 index 1e4a7e57..00000000 --- a/doc/nixos/tutorials/archiver-appliance.md +++ /dev/null @@ -1,359 +0,0 @@ ---- -title: Creating an Archiver Appliance instance ---- - -In this tutorial, -we're going to see how to create a virtual machine that runs Archiver Appliance, -under the NixOS Linux distribution. - -Installing Archiver Appliance on a physical machine is definitely possible, -but this tutorial focuses on virtual machines for simplicity's sake. - -You will need: - -- A virtual machine, -- and the [NixOS ISO file]. - Select the "Graphical ISO image." - - [NixOS ISO file]: https://nixos.org/download#download-nixos - -# Installing NixOS - -First things first, -create your virtual machine, -and select the ISO image that you downloaded. - -Then, start the virtual machine. - -From the booted virtual machine, -you can follow the graphical installation process, -and reboot once finished. - -You can select any desktop environment, -or no desktop. -This tutorial only uses the command-line. - -# Making your configuration a flake - -The installation process created the `/etc/nixos` directory in your VM. -This directory describes the complete configuration of your machine. - -EPNix is a "Nix flake", -which a way of managing Nix projects. -Using Nix flakes also enables you to use Nix code outside of your repository, -in a controlled manner. -For more information, -see the [Nix flake command manual] and the [Flake wiki page]. - -To be able to import EPNix into you NixOS configuration, -you first need to turn your NixOS configuration into a Nix flake. - -As root, place yourself in the `/etc/nixos` directory in your virtual machine. -Create a `flake.nix` file under it, -by running `nano flake.nix`. -Fill the file with these lines: - -``` {.nix filename="flake.nix" code-line-numbers="true"} -{ - description = "Configuration for running Archiver Appliance in a VM"; - - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; - inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; - - outputs = { self, nixpkgs, epnix }: { - nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { - modules = [ - epnix.nixosModules.nixos - - ./configuration.nix - ]; - }; - }; -} -``` - -Save and quit by typing {{< kbd Ctrl-x >}}, {{< kbd y >}}, and {{< kbd Enter >}}, -and run `nixos-rebuild test` to test your changes. - -Some explanations: - -You can see in the `flake.nix` file that the flake has 2 inputs: -`nixpkgs` and `epnix`, -lines 4--5. - -Having the `nixpkgs` input enables you to use code from [Nixpkgs]. -This is what enables you to use all those NixOS options, -and every package installed on your machine now. -For more information, -you can read the [Nixpkgs preface] -With the current configuration, -we are only using code from Nixpkgs. - -Having the `epnix` input is what's going to enable you to use [packages from EPNix], -such as Archiver Appliance. -It also enables you to use [EPNix' extra NixOS options], -such as the options configuring Tomcat, the systemd service, the `archappl` user and group, MariaDB, and so on. - - [Nix flake command manual]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html - [Flake wiki page]: https://nixos.wiki/wiki/Flakes - [Nixpkgs]: https://github.com/NixOS/nixpkgs - [Nixpkgs preface]: https://nixos.org/manual/nixpkgs/stable/#preface - [packages from EPNix]: ../../pkgs/packages.md - [EPNix' extra NixOS options]: ../options.md - -# Configuring Archiver Appliance - -Now for the fun part, -actually using those EPNix options to install and configure Archiver Appliance, -and all its dependencies. - -Create and edit the file `archiver-appliance.nix` under `/etc/nixos`. -For now, here are the contents: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance.enable = true; -} -``` - -In your `flake.nix`, -import the newly created file by adding `./archiver-appliance.nix`, -under `./configuration.nix`: - -``` diff - modules = [ - epnix.nixosModules.nixos - - ./configuration.nix -+ ./archiver-appliance.nix - ]; -``` - -If you try to test your changes by running `nixos-rebuild test`, -you will see a helpful error message: - -::: sourceCode -``` sourcecode -error: The option `services.archiver-appliance.stores.lts.location' - is used but not defined. -(use '--show-trace' to show detailed location information) -``` -::: - -This tells you that the `services.archiver-appliance.stores.lts.location` is mandatory, -but we didn't set any value. - -To figure out what this option is about, -you can examine the [options reference]. - -The options reference gives a description for this option: - -> Backing directory containing the LTS. - -and an example: - -``` nix -"/data/lts" -``` - -It tells us that you need to choose where the Long Term Store (LTS) is. -See the "Architecture" section of the [Archiver Appliance Details] page for what the various stores are. - -Because this is a test VM, -let's configure the LTS to a test location, -like `/tmp/lts`. -You will also need to configure the location of the Medium Term Store (MTS). - -Here's how to change `archiver-appliance.nix`: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance.enable = true; - services.archiver-appliance.stores.lts.location = "/tmp/lts"; - services.archiver-appliance.stores.mts.location = "/tmp/mts"; -} -``` - -If you don't want to repeat yourself, -you can also change it like so: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance = { - enable = true; - stores.lts.location = "/tmp/lts"; - stores.mts.location = "/tmp/mts"; - }; -} -``` - -And now, -`nixos-rebuild test` should succeed: - -::: sourceCode -``` sourcecode -building the system configuration... -activating the configuration... -setting up /etc... -reloading user units for admin... -setting up tmpfiles -reloading the following units: dbus.service -the following new units were started: arch-lts-ArchiverStore.mount, - arch-mts-ArchiverStore.mount, arch-sts-ArchiverStore.mount, - mysql.service, tomcat.service -``` -::: - -From the message, -we can guess it started the Tomcat server running Archiver Appliance, -the MySQL (in fact, MariaDB) server, -and mounted some partitions. -Fantastic! - -You can run the `systemctl list-units` command to see if any systemd unit failed. - -In the default configuration, -Archiver Appliance and Tomcat are configured to output logs to journald. -You can see those logs by running: - -``` bash -journalctl -xeu tomcat.service -``` - -You can also see the MariaDB logs by running: - -``` bash -journalctl -xeu mysql.service -``` - -::: callout-note -Here are some details on what was done by EPNix' `services.archiver-appliance` NixOS module: - -- Creation of the Linux user and group `archappl` -- Installation and configuration of MariaDB: - - Creation of the `archappl` user, - with UNIX socket authentication - - Creation of the Archiver Appliance database - - Creation of the [various tables] in that database - - Giving access rights to this database for the `archappl` user -- Installation and configuration of Tomcat: - - Installation of the WAR files of Archiver Appliance - - Installation of the MariaDB connector and its dependencies - - Configuring the MariaDB connector to authenticate to the database - - Logging configuration to `journald` -- Configuring mounts so that: - - `/arch/lts` and `/arch/mts` are bind mounts to the configured locations, - with some added security options, - such as `nodev` and `noexec` - - Mounting `/arch/sts` as a new `tmpfs` -::: - -Tomcat runs by default under port 8080, -and NixOS has a firewall enabled by default. - -Change your `archiver-appliance.nix`: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance = { - enable = true; - stores.lts.location = "/tmp/lts"; - stores.mts.location = "/tmp/mts"; - - # New option: - openFirewall = true; - }; -} -``` - -and run `nixos-rebuild test`. -It will restart `firewall.service`, -but configured to allow incoming connection on port 8080. - -Check the IP address of your VM with `ip a`, -and open a browser to `http://:8080/mgmt/ui/index.html`. - -Finally, -run `nixos-rebuild switch` to confirm your changes. -This will apply your changes for the next reboot, -by adding a new boot entry, -enabling you to go back to a previous configuration. - -You have now configured Archiver Appliance on NixOS. - - [options reference]: ../options.md - [Archiver Appliance Details]: https://slacmshankar.github.io/epicsarchiver_docs/details.html - [various tables]: https://github.com/slacmshankar/epicsarchiverap/blob/master/src/main/org/epics/archiverappliance/config/persistence/archappl_mysql.sql - -# Next steps - -This VM configuration has some problems: - -- It stores the LTS and MTS in `/tmp`, - which by default is cleaned on reboot -- The size of the Short Term Store (STS) isn't configured -- Both "management" and "retrieval" URLs are accessible without authentication - -The following sections are some pointers to fix these issues. - -## Configuring partitions - -If you want to change the location of the LST or MTS, -you can change the value of the corresponding options: - -- `services.archiver-appliance.stores.lts.location` -- `services.archiver-appliance.stores.mts.location` - -But these values won't mean much if the configured directories are not backed by the appropriate hardware. - -As an example given by the [Archiver Appliance Details] page, -section "Architecture", -we can have the LTS backed by a NAS or SAN, -and the MTS backed by SSD or SAS storage. - -The way to do that is to configure the `fileSystems` NixOS option. -See the [File Systems NixOS documentation] for more information. - - [Archiver Appliance Details]: https://slacmshankar.github.io/epicsarchiver_docs/details.html - [File Systems NixOS documentation]: https://nixos.org/manual/nixos/stable/#ch-file-systems - -## Size of the short term store - -To configure the size of the short term store, -use the `services.archiver-appliance.stores.sts.size` option. - -For example: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance = { - enable = true; - stores.lts.location = "/tmp/lts"; - stores.mts.location = "/tmp/mts"; - - openFirewall = true; - - # New option: - stores.sts.size = "20g"; - }; -} -``` - -See the [`sts.size` option] in the reference for a more in-depth description. - - [`sts.size` option]: ../options.md#services.archiver-appliance.stores.sts.size - -## Restricting access - -Allowing access to `mgmt` URLs to anyone can be dangerous, -because it allows anyone to delete and archive PVs. - -To restrict access, -you can close the firewall and put an nginx server in front. - -You can configure the nginx server to disallow access to the URLs you want. -You can also configure nginx to require authentication. - -```{=html} - -``` diff --git a/doc/pkgs/introduction.md b/doc/pkgs/introduction.md deleted file mode 100644 index 7baabb9d..00000000 --- a/doc/pkgs/introduction.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Packages ---- - -# Introduction diff --git a/pkgs/book/default.nix b/pkgs/book/default.nix deleted file mode 100644 index 23fcc96d..00000000 --- a/pkgs/book/default.nix +++ /dev/null @@ -1,109 +0,0 @@ -{ - stdenvNoCC, - lib, - epnixLib, - epnix, - quartoMinimal, - writeText, - documentedEpnixPkgs ? epnix, - iocConfig ? {}, - nixosConfig ? {}, -}: let - inherit (epnixLib) documentation; - - iocOptions = documentation.options.iocOptions iocConfig; - nixosOptions = documentation.options.nixosOptions nixosConfig; - - iocOptionsContent = documentation.options.optionsContent iocOptions 1; - iocOptionsPandoc = '' - --- - title: Options - format: - html: - # Disable the smart extensions so that the quotes in option names are not replaced - from: markdown-smart - --- - - ${iocOptionsContent} - ''; - - nixosOptionsContent = documentation.options.optionsContent nixosOptions 1; - nixosOptionsPandoc = '' - --- - title: NixOS Options - format: - html: - # Disable the smart extensions so that the quotes in option names are not replaced - from: markdown-smart - --- - - ${nixosOptionsContent} - ''; - - iocPkgsListPandoc = '' - --- - title: Packages list - --- - - ::: callout-note - This page references all EPNix packages that should be used when packaging an IOC. - For all other packages, see the [Packages list](../../pkgs/packages.md). - ::: - - ${epnixLib.documentation.iocPkgsList 1 documentedEpnixPkgs} - ''; - - pkgsListPandoc = '' - --- - title: Packages list - --- - - ::: callout-note - This page references all EPNix packages that may be used outside of an IOC. - For all IOC-specific packages, see the [IOC packages list](../ioc/references/packages.md). - ::: - - ${epnixLib.documentation.pkgsList 1 documentedEpnixPkgs} - ''; -in - stdenvNoCC.mkDerivation { - name = "epnix-book"; - src = ../../doc; - - nativeBuildInputs = [quartoMinimal]; - - dontConfigure = true; - - buildPhase = '' - runHook preBuild - - export HOME=$PWD - - mkdir ioc/references - - cp "${writeText "ioc-options.md" iocOptionsPandoc}" ioc/references/options.md - cp "${writeText "ioc-packages.md" iocPkgsListPandoc}" ioc/references/packages.md - cp "${writeText "nixos-options.md" nixosOptionsPandoc}" nixos/options.md - cp "${writeText "packages.md" pkgsListPandoc}" pkgs/packages.md - - quarto render - - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - - cp -r _site/ "$out" - - runHook postInstall - ''; - - meta = { - description = "The EPNix documentation book"; - homepage = "https://epics-extensions.github.io/EPNix/"; - license = lib.licenses.asl20; - maintainers = with epnixLib.maintainers; [minijackson]; - hidden = true; - }; - } diff --git a/pkgs/default.nix b/pkgs/default.nix index 35f64cab..02ba4f3b 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -88,9 +88,7 @@ in mariadb_jdbc = callPackage ./epnix/tools/mariadb_jdbc {}; # EPNix specific packages - book = callPackage ./book {}; docs = callPackage ./docs {}; - manpages = callPackage ./manpages {}; # Documentation support packages psu-simulator = callPackage ./doc-support/psu-simulator {}; diff --git a/pkgs/manpages/default.nix b/pkgs/manpages/default.nix deleted file mode 100644 index 0027c55c..00000000 --- a/pkgs/manpages/default.nix +++ /dev/null @@ -1,117 +0,0 @@ -{ - stdenvNoCC, - lib, - epnix, - epnixLib, - emptyDirectory, - writeText, - pandoc, - documentedEpnixPkgs ? epnix, - iocConfig ? {}, - nixosConfig ? {}, -}: let - inherit (epnixLib) documentation; - - iocOptions = documentation.options.iocOptions iocConfig; - nixosOptions = documentation.options.nixosOptions nixosConfig; - - iocOptionsContent = documentation.options.optionsContent iocOptions 2; - iocPandoc = '' - --- - title: epnix-ioc - section: 5 - header: EPNix IOC options and packages - --- - - # PACKAGES - - This section references all EPNix packages that should be used when packaging an IOC. - For all other packages, see `epnix-packages(5)`. - - ${epnixLib.documentation.iocPkgsList 2 documentedEpnixPkgs} - - --- - - # OPTIONS - - ${iocOptionsContent} - - # SEE ALSO - - `epnix-nixos(5)`, `epnix-packages(5)` - ''; - - nixosOptionsContent = documentation.options.optionsContent nixosOptions 2; - nixosOptionsPandoc = '' - --- - title: epnix-nixos - section: 5 - header: EPNix NixOS options - --- - - # OPTIONS - - ${nixosOptionsContent} - - # SEE ALSO - - `epnix-ioc(5)`, `epnix-packages(5)` - ''; - - pkgsListPandoc = '' - --- - title: epnix-packages - section: 5 - header: EPNix packages - --- - - # DESCRIPTION - - This page references all EPNix packages that may be used outside of an IOC. - For all IOC-specific packages, see `epnix-ioc(5)`. - - # PACKAGES - - ${epnixLib.documentation.pkgsList 2 documentedEpnixPkgs} - - # SEE ALSO - - `epnix-ioc(5)`, `epnix-nixos(5)` - ''; -in - stdenvNoCC.mkDerivation { - name = "epnix-manpages"; - src = emptyDirectory; - - nativeBuildInputs = [pandoc]; - - dontConfigure = true; - - buildPhase = '' - runHook preBuild - - pandoc "${writeText "ioc-options.md" iocPandoc}" -t man -so epnix-ioc.5 - pandoc "${writeText "nixos-options.md" nixosOptionsPandoc}" -t man -so epnix-nixos.5 - pandoc "${writeText "epnix-packages.md" pkgsListPandoc}" -t man -so epnix-packages.5 - - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - - install -Dt $out/share/man/man5/ epnix-ioc.5 epnix-nixos.5 epnix-packages.5 - # Add the bin folder so that the man path gets added to `manpath` - mkdir -p $out/bin - - runHook postInstall - ''; - - meta = { - description = "The EPNix documentation man page"; - homepage = "https://epics-extensions.github.io/EPNix/"; - license = lib.licenses.asl20; - maintainers = with epnixLib.maintainers; [minijackson]; - hidden = true; - }; - }