NIXOPS(1)
π NAME π
nixops β NixOps 2.0, and yes bestie, this is NIXOPS(1). π«Ά
π INTRODUCTION π
okay so NixOps is a tool for deploying NixOS machines in a network or cloud, and it is lowkey iconic. It takes as input a declarative specification of a set of βlogicalβ machines and then performs any necessary steps or actions to realise that specification: instantiate cloud machines, build and download dependencies, stop and start services, and so on. NixOps has several nice properties:
- Itβs declarative: NixOps specifications state the desired configuration of the machines, and NixOps then figures out the actions necessary to realise that configuration. So there is no difference between doing a new deployment or doing a redeployment: the resulting machine configurations will be the same. β¨
- It performs fully automated deployment. This is a good thing because it ensures that deployments are reproducible. π
- It performs provisioning. Based on the given deployment specification, it will start missing virtual machines, create disk volumes, and so on. π
- Itβs based on the Nix package manager (
http://nixos.org/nix/), which has a purely functional model that sets it apart from other package managers. Concretely this means that multiple versions of packages can coexist on a system, that packages can be upgraded or rolled back atomically, that dependency specifications can be guaranteed to be complete, and so on. π§ - Itβs based on NixOS (
http://nixos.org/nixos/), which has a declarative approach to describing the desired configuration of a machine. This makes it an ideal basis for automated configuration management of sets of machines. NixOS also has desirable properties such as (nearly) atomic upgrades, the ability to roll back to previous configurations, and more. πΈ - Itβs multi-cloud. Machines in a single NixOps deployment can be deployed to different target environments. For instance, one logical machine can be deployed to a local βphysicalβ machine, another to an automatically instantiated Amazon EC2 instance in the
eu-west-1region, another in theus-east-1region, and so on. βοΈ - It supports separation of βlogicalβ and βphysicalβ aspects of a deployment. NixOps specifications are modular, and this makes it easy to separate the parts that say what logical machines should do from where they should do it. For instance, the former might say that machine X should run a PostgreSQL database and machine Y should run an Apache web server, while the latter might state that X should be instantiated as an EC2
m1.largemachine while Y should be instantiated as anm1.small. We could also have a second physical specification that says that X and Y should both be instantiated as VirtualBox VMs on the developerβs workstation. So the same logical specification can easily be deployed to different environments. π¦ - It uses a single formalism (the Nix expression language) for package management and system configuration management. This makes it very easy to add ad hoc packages to a deployment. π
- It combines system configuration management and provisioning. Provisioning affects configuration management: for instance, if we instantiate an EC2 machine as part of a larger deployment, it may be necessary to put the IP address or hostname of that machine in a configuration file on another machine. NixOps takes care of this automatically. π₯
- It can provision non-machine cloud resources such as Amazon S3 buckets and EC2 key pairs. π
π OVERVIEW π
Okay so this section is the quick lil' map of how to use NixOps, bestie. No cap, it's giving "here's the whole vibe before we get into the nitty-gritty." π
π Deploying to a NixOS machine π
To deploy to a machine that's already running NixOS, simply set deployment.targetHost to the IP address or host name of the machine, and leave deployment.targetEnv undefined. Easy peasy. See trivial-nixos.nix: NixOS target physical network specification.
trivial-nixos.nix: NixOS target physical network specification
{
webserver =
{ config, pkgs, ... }:
{ deployment.targetHost = "1.2.3.4";
};
}
π Accessing machines π
You can login to individual machines by doing nixops ssh name, where name is the name of the machine. Obsessed with a direct lil' SSH moment. β¨
It's also possible to perform a command on all machines:
$ nixops ssh-for-each -d load-balancer-ec2 -- df /tmp
backend1...> /dev/xvdb 153899044 192084 145889336 1% /tmp
proxy......> /dev/xvdb 153899044 192084 145889336 1% /tmp
backend2...> /dev/xvdb 153899044 192084 145889336 1% /tmp
By default, the command is executed sequentially on each machine. You can add the flag to execute it in parallel. πββοΈπ¨
π©Ί Checking machine status π©Ί
The command nixops check checks the status of each machine in a deployment. It verifies that the machine still exists (i.e. hasn't been destroyed outside of NixOps), is up (i.e. the instance has been started) and is reachable via SSH. It also checks that any attached disks (such as EBS volumes) are not in a failed state, and prints the names of any systemd units that are in a failed state. It's literally the vibe check for your deployment. π«Ά
For example, for the 3-machine EC2 network shown above, it might show:
$ nixops check -d load-balancer-ec2
+----------+--------+-----+-----------+----------+----------------+---------------+-------+
| Name | Exists | Up | Reachable | Disks OK | Load avg. | Failed units | Notes |
+----------+--------+-----+-----------+----------+----------------+---------------+-------+
| backend1 | Yes | Yes | Yes | Yes | 0.03 0.03 0.05 | httpd.service | |
| backend2 | Yes | No | N/A | N/A | | | |
| proxy | Yes | Yes | Yes | Yes | 0.00 0.01 0.05 | | |
+----------+--------+-----+-----------+----------+----------------+---------------+-------+
This indicates that Apache httpd has failed on backend1 and that machine backend2 is not running at all. In this situation, you should run nixops deploy --check to repair the deployment. Fix it bestie, you got this. π
πΈ Network special attributes πΈ
It is possible to define special options for the whole network. For example:
{
network = {
description = "staging environment";
enableRollback = true;
};
defaults = {
imports = [ ./common.nix ];
};
machine = { ... }: {};
}
Each attribute is explained below:
defaultsβ applies given NixOS module to all machines defined in the network.network.descriptionβ a sentence describing the purpose of the network for easier comparison when runningnixops list.network.enableRollbackβ if true, each deployment creates a new profile generation to able to runnixops rollback. Defaults tofalse.
π Network arguments π
In NixOps you can pass in arguments from outside the nix expression. The network file can be a nix function, which takes a set of arguments which are passed in externally and can be used to change configuration values, or even to generate a variable number of machines in the network. It's giving "parameterized network, main character energy." π
Here is an example of a network with network arguments:
{ maintenance ? false
}:
{
machine =
{ config, pkgs, ... }:
{ services.httpd.enable = maintenance;
...
};
}
This network has a maintenance argument that defaults to false. This value can be used inside the network expression to set NixOS option, in this case whether or not Apache HTTPD should be enabled on the system.
You can pass network arguments using the set-args nixops command. For example, if we want to set the maintenance argument to true in the previous example, you can run:
$ nixops set-args --arg maintenance true -d argtest
The arguments that have been set will show up:
$ nixops info -d argtest
Network name: argtest
Network UUID: 634d6273-f9f6-11e2-a004-15393537e5ff
Network description: Unnamed NixOps network
Nix expressions: .../network-arguments.nix*Nix arguments: maintenance = true*
+---------+---------------+------+-------------+------------+
| Name | Status | Type | Resource Id | IP address |
+---------+---------------+------+-------------+------------+
| machine | Missing / New | none | | |
+---------+---------------+------+-------------+------------+
Running nixops deploy after changing the arguments will deploy the new configuration. Slay. β¨
ποΈ Managing keys ποΈ
Files in /nix/store/ are readable by every user on that host, so storing secret keys embedded in nix derivations is insecure. To address this, nixops provides the configuration option deployment.keys, which nixops manages separately from the main configuration derivation for each machine. Very "don't put your secrets in the group chat" of it. π
Add a key to a machine like so.
{
machine =
{ config, pkgs, ... }:
{
deployment.keys.my-secret.text = "shhh this is a secret";
deployment.keys.my-secret.user = "myuser";
deployment.keys.my-secret.group = "wheel";
deployment.keys.my-secret.permissions = "0640";
};
}
This will create a file /run/keys/my-secret with the specified contents, ownership, and permissions.
Only the contents of the secret is required. It can be specified using one of the options text, keyFile or keyCommand. The user and group options both default to "root", and permissions defaults to "0600".
Keys from deployment.keys are stored under /run/ on a temporary filesystem and will not persist across a reboot. To send a rebooted machine its keys, use nixops send-keys. Note that all nixops commands implicitly upload keys when appropriate, so manually sending keys should only be necessary after an unattended reboot. π«‘
If you have a custom service that depends on a key from deployment.keys, you can opt to let systemd track that dependency. Each key gets a corresponding systemd service "${keyname}-key.service" which is active while the key is present, and otherwise inactive when the key is absent. See key-dependency.nix: track key dependence with systemd for how to set this up.
key-dependency.nix: track key dependence with systemd
{
machine =
{ config, pkgs, ... }:
{
deployment.keys.my-secret.text = "shhh this is a secret";
systemd.services.my-service = {
after = [ "my-secret-key.service" ];
wants = [ "my-secret-key.service" ];
script = ''
export MY_SECRET=$(cat /run/keys/my-secret)
run-my-program
'';
};
};
}
These dependencies will ensure that the service is only started when the keys it requires are present. For example, after a reboot, the services will be delayed until the keys are available, and systemctl status and friends will lead you to the cause. It's literally systemd holding the key for you. π
π§ Special NixOS module inputs π§
In deployments with multiple machines, it is often convenient to access the configuration of another node in the same network, e.g. if you want to store a port number only once.
This is possible by using the extra NixOS module input nodes.
{
network.description = "Gollum server and reverse proxy";
gollum =
{ config, pkgs, ... }:
{
services.gollum = {
enable = true;
port = 40273;
};
networking.firewall.allowedTCPPorts = [ config.services.gollum.port ];
};
reverseproxy =
{ config, pkgs, nodes, ... }:
let
gollumPort = nodes.gollum.config.services.gollum.port;
in
{
services.nginx = {
enable = true;
virtualHosts."wiki.example.net".locations."/" = {
proxyPass = "http://gollum:${toString gollumPort}";
};
};
networking.firewall.allowedTCPPorts = [ 80 ];
};
}
Moving the port number to a different value is now without the risk of an inconsistent deployment. Iconic. π
Additional module inputs are
nameβ The name of the machine.uuidβ The NixOps UUID of the deployment.resourcesβ NixOps resources associated with the deployment.
πΈ DEPLOYING WITHOUT ROOT πΈ
π§ Requirements π§
NixOps 2.0 allows for deploying as users other than root, as long as the deploying user meets two requirements:
- The user can become root without needing to type a password.
- Nix considers the user to be a "trusted user" (
https://nixos.org/nix/manual/#conf-trusted-users).
In this guide, we will use passwordless sudo. Very "root energy without being root" of it. π
We assume:
- The deploying user's name is
"deployer". - The target machine's name is
"hermes". - The target machine is already managed by NixOps.
π Steps π
- Configure the target machine according to the listed requirements.
- Update the NixOps network to use our alternative user.
- Deploy as the new user.
π οΈ Configuring the Target Machine π οΈ
First, mark the deploying user as trusted:
{
nix.trustedUsers = [ "deployer" ];
}
This will let the user copy Nix store paths to the target.
Let the deploying user use sudo:
{
users.users.deployer.extraGroups = [ "wheel" ];
}
Then, we configure the machine to have passwordless sudo:
{
security.sudo.wheelNeedsPassword = false;
}
Now use NixOps to deploy these changes to the server before taking the next step.
π Configuring the NixOps Network π
Edit your nixops.nix to specify the machine's deployment.targetUser:
{
network.description = "Non-root deployment";
hermes =
{ resources, ... }:
{
deployment.targetUser = "deployer";
};
}
π§ͺ Testing our Changes π§ͺ
Then, run nixops deploy to update the NixOps database. This deploy will use your "deployer" user instead of root.
Try running nixops ssh, and see that you are logged in as "deployer". Periodt. π
π Notes π
- NixOps caches the target user and related variables in its state file, and commands like
nixops send-keysandsshuse the cached data. After changing these values, runnixops deployto update the cache.
π οΈ AUTHORING A PLUGIN π οΈ
okay so NixOps plugins are literally how you make NixOps core do more β like supporting extra hosting providers and resource types. that's the whole vibe. π
some example plugins, so you can see what we're talking about (go look at them, bestie, they're iconic):
- <https://github.com/NixOS/nixops-aws>
- <https://github.com/NixOS/nixops-hetzner>
- <https://github.com/nix-community/nixops-vbox>
- <https://github.com/nix-community/nixops-libvirtd>
- <https://github.com/nix-community/nixops-datadog>
fr fr this guide is light on the details on purpose β it just wants to describe the supported hooks and the integration process. that's it. no cap.
πΈ Packaging with Poetry and poetry2nix πΈ
NixOps and its plugins are packaged as standard Python applications. most packages will use Poetry <https://python-poetry.org> and poetry2nix <https://github.com/nix-community/poetry2nix> for packaging with Nix. slay.
Note: NixOps is formatted withblackand strictly typechecked withmypy. your project should follow these guidelines too β and use amypyconfiguration at least as strict as the NixOpsmypyconfiguration. no shortcuts, bestie. π€
first up, create a pyproject.toml (see PEP-0517 <https://www.python.org/dev/peps/pep-0517/>) to describe your project. we do not use setup.py, and trying to use both a setup.py and pyproject.toml may cause confusing build errors. only use a pyproject.toml:
[tool.poetry]
name = "nixops_neatcloud"
version = "1.0"
description = "NixOps plugin for NeatCloud"
authors = ["Your Name <your.name@example.com>"]
license = "MIT"
include = [ "nixops_neatcloud/nix/*.nix" ]
[tool.poetry.dependencies]
python = "^3.7"
nixops = {git = "https://github.com/NixOS/nixops.git", rev = "master"}
[tool.poetry.dev-dependencies]
mypy = "^0.770"
black = "^19.10b0"
[tool.poetry.plugins."nixops"]
neatcloud = "nixops_neatcloud.plugin"
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
π Important Notes π
read these. all of them. they're giving "final boss of migration" energy but they're short, i promise. π«Ά
- if you have a
setup.py, delete it now. like, right now. - if your plugin is named
nixops_neatcloud, the source directory must be namednixops_neatcloud. - if your source directory was named
nixopsneatcloud, please rename it tonixops_neatcloud. - older style plugins used to store the Nix expressions in a directory named
nixnext to the python plugin directory, like this:
.
βββ nix
β βββ default.nix
βββ nixops_neatcloud
βββ __init__.py
βββ plugin.py
plugins must now put the nix expressions underneat the plugin's python directory:
.
βββ nixops_neatcloud
βββ nix
β βββ default.nix
βββ __init__.py
βββ plugin.py
and the nixexprs hook function which looked like this:
@nixops.plugins.hookimpl
def nixexprs():
expr_path = os.path.realpath(os.path.dirname(__file__) + "/../../../../share/nix/nixops-vbox")
if not os.path.exists(expr_path):
expr_path = os.path.realpath(os.path.dirname(__file__) + "/../../../../../share/nix/nixops-vbox")
if not os.path.exists(expr_path):
expr_path = os.path.dirname(__file__) + "/../nix"
return [
expr_path
]
can now look like this:
from nixops.plugins import Plugin
class NeatCloudPlugin(Plugin):
@staticmethod
def nixexprs():
return [
os.path.dirname(os.path.abspath(__file__)) + "/nix"
]
- resource subclasses must now work with Python objects instead of XML. this is the glow-up, honestly. β¨
this old-style ResourceDefinition subclass:
class NeatCloudMachineDefinition(nixops.resources.ResourceDefinition):
def __init__(self, xml):
super().__init__(xml)
self.store_keys_on_machine = (
xml.find("attrs/attr[@name='storeKeysOnMachine']/bool").get("value")
== "true"
)
should now look like:
class NeatCloudMachineOptions(nixops.resources.ResourceOptions):
storeKeysOnMachine: bool
class NeatCloudMachineDefinition(nixops.resources.ResourceDefinition):
config: MachineOptions
store_keys_on_machine: bool
def __init__(self, name: str, config: nixops.resources.ResourceEval):
super().__init__(name, config)
self.store_keys_on_machine = config.storeKeysOnMachine
ResourceEval is an immutable typing.Mapping implementation. also note that ResourceEval has turned Nix lists into Python tuples, dictionaries into ResourceEval objects and so on. typing.Tuple cannot be used as it's fixed-size β use typing.Sequence instead. iykyk. π₯
ResourceOptions is an immutable object that provides type validation both with mypy and at runtime. any attributes which are not explicitly typed are passed through as-is.
β¨ On with Poetry β¨
now create your first poetry.lock file with poetry lock:
nixops_neatcloud$ nix-shell -p poetry
[nix-shell:nixops_neatcloud]$ poetry lock
Creating virtualenv nixops_neatcloud-FrXThxiS-py3.7 in ~/.cache/pypoetry/virtualenvs
Updating dependencies
Resolving dependencies... (2.1s)
Writing lock file
exit the Nix shell, and create the supporting Nix files.
create a default.nix:
{ pkgs ? import <nixpkgs> {} }:
let
overrides = import ./overrides.nix { inherit pkgs; };
in pkgs.poetry2nix.mkPoetryApplication {
projectDir = ./.;
overrides = pkgs.poetry2nix.overrides.withDefaults overrides;
}
and a minimal overrides.nix:
{ pkgs }:
self: super: {
nixops = super.nixops.overridePythonAttrs({ nativeBuildInputs ? [], ... }: {
format = "pyproject";
nativeBuildInputs = nativeBuildInputs ++ [ self.poetry ];
});
}
and finally, a shell.nix:
{ pkgs ? import <nixpkgs> {} }:
let
overrides = import ./overrides.nix { inherit pkgs; };
in pkgs.mkShell {
nativeBuildInputs = [
pkgs.poetry
];
buildInputs = [
(pkgs.poetry2nix.mkPoetryEnv {
projectDir = ./.;
overrides = pkgs.poetry2nix.overrides.withDefaults overrides;
})
];
}
now you can enter a Nix and Poetry shell to develop on your plugin. main character energy activated. π
nixops_neatcloud$ nix-shell
[nix-shell:nixops_neatcloud]$ poetry install
[nix-shell:nixops_neatcloud]$ poetry shell
Note: install is making a virtual environment, and does not install anything in the traditional sense. it's giving "it's not what you think" but in a good way. π
create an empty file at nixops_neatcloud/plugin.py, and then you'll be able to list plugins and see your plugin:
now you can list plugins and see your plugin is installed:
(nixops_neatcloud-FrXThxiS-py3.7)
nixops_neatcloud$ nixops list-plugins
+-------------------+
| Installed Plugins |
+-------------------+
| neatcloud |
+-------------------+
at this point, you can develop your plugin from within this shell, running nixops and mypy nixops_neatcloud./
π§ Plug-in Loading π§
NixOps uses Pluggy <https://pluggy.readthedocs.io/en/latest/> to discover and load plugins. the glue which hooks things together is in pyproject.toml:
[tool.poetry.plugins."nixops"]
neatcloud = "nixops_neatcloud.plugin"
NixOps implements a handful of hooks which your plugin can integrate with. see nixops/plugins/hookspec.py for a complete list. that file is your bestie, genuinely. π¦
π Defining a plugin π
to define a plugin you need to inherit from the Plugin base class and return it in the appropriate plugin hook:
from nixops.plugins import Plugin
import nixops.plugins
class NeatCloudPlugin(Plugin):
@staticmethod
def nixexprs():
return [ ] # List of paths to nix expressions
@nixops.plugins.hookimpl
def plugin():
return NeatCloudPlugin()
π«Ά Developing NixOps and a plugin at the same time π«Ά
in this case you want a mutable copy of NixOps and your plugin. since we are developing the plugin like any other Python program, we can specify a relative path to NixOps's source in the pyproject.toml:
nixops = { path = "../nixops" }
then run poetry lock; poetry install; poetry shell like normal. easy. periodt. π
π©Ή Troubleshooting π©Ή
if you run in to trouble, you might try deleting some things:
$ rm -rf nixops_neatcloud.egg-info pip-wheel-metadata/
π₯ Building a dependency fails π₯
first, run your nix-shell or nix-build with --keep-going and then again with --jobs 1 to isolate the cause. the first run will build everything it can complete, and the second one will build only one derivation and then fail:
nixops_neatcloud$ nix-shell -j1 --keep-going
these derivations will be built:
/nix/store/3s2a0hky73b24m4yppd7581c9w2clpnb-python3.7-nixops-1.8.0.drv
/nix/store/bv6gwayic2xxx3pd489d4gbs03kafxsd-python3-3.7.6-env.drv
building '/nix/store/3s2a0hky73b24m4yppd7581c9w2clpnb-python3.7-nixops-1.8.0.drv'...
[...]
Traceback (most recent call last):
File "nix_run_setup", line 8, in <module>
exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
File "/nix/store/n8nviwmllwqv0fjsar8v8k8gjap1vhcw-python3-3.7.6/lib/python3.7/tokenize.py", line 447, in open
buffer = _builtin_open(filename, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: 'setup.py'
builder for '/nix/store/3s2a0hky73b24m4yppd7581c9w2clpnb-python3.7-nixops-1.8.0.drv' failed with exit code 1
cannot build derivation '/nix/store/bv6gwayic2xxx3pd489d4gbs03kafxsd-python3-3.7.6-env.drv': 1 dependencies couldn't be built
error: build of '/nix/store/bv6gwayic2xxx3pd489d4gbs03kafxsd-python3-3.7.6-env.drv' failed
if a dependency is missing, add the dependency to your pyproject.toml, and add an override like the Toml example for Zipp. π
π Zipp can't find toml π
add zipp to your overrides.nix, providing toml explicitly:
{ pkgs }:
self: super: {
zipp = super.zipp.overridePythonAttrs({ propagatedBuildInputs ? [], ... } : {
propagatedBuildInputs = propagatedBuildInputs ++ [
self.toml
];
});
}
π FileNotFoundError: [Errno 2] No such file or directory: 'setup.py' π
this dependency needs to be built in the pyproject format, which means it will also need poetry as a dependency. add this to your overrides.nix:
package-name = super.package-name.overridePythonAttrs({ nativeBuildInputs ? [], ... }: {
format = "pyproject";
nativeBuildInputs = nativeBuildInputs ++ [ self.poetry ];
});
π MIGRATING FROM NIXOPS 1 π
Overview <>
π COMMAND REFERENCE
Description <>
(it literally just says that, bestie β empty angle brackets, nothing else. We move π«Ά)
β¨ CONFIGURATION OPTIONS β¨
π₯οΈ Machines
NixOps slides a whole bunch of extra options into the NixOS machine configuration system. For the standard NixOS configuration options β the vanilla ones β go check the NixOS manual (http://hydra.nixos.org/job/nixos/trunk/manual/latest/download) or the configuration.nix5 man page. iykyk π
π RELEASE NOTES
(okay so this heading is just... here. Sitting alone. Nothing under it in the source. The real release notes are further down, girl, we'll get there π)
π WRITING DOCUMENTATION
New NixOps documentation uses a standard configuration of Sphinx. The older documentation is in Docbook, and honestly it should be ported to reStructuredText. Glow-up pending β¨
Sphinx's primer on reStructuredText (reST) lives right here: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html.
The NixOps repo has live-reloading support, which is lowkey iconic:
nixops$ ./live-docs.py
Serving on http://127.0.0.1:5500
Open http://127.0.0.1:5500 in your browser. As you edit and save .rst files, your browser automatically reloads. No more manual refreshing bestie, we're literally in the future π
β Before Committing
Validate the source files for correctly written reST and spelling:
nixops$ ./ci/lint-docs.sh
Fix any errors before committing. Fr fr. Not optional π
π RELEASE NOTES
π Release 2.0
- The code base has been migrated to Python 3. π slay
- The code base has been statically typed with Mypy.
- Backends are now developed as separate plugins.
- Poetry & Poetry2nix are used for packaging.
- Separate state backends for storing state.
- Major code cleanups.
- Removed the
nixops create <file>file argument. It now requires aflake.nixornixops.nixfile. - Removed NixOS Options:
deployment.autoLuks.*β moved to nixos-modules-contrib (https://github.com/nix-community/nixos-modules-contrib).deployment.autoRaid0.*β moved to nixos-modules-contrib (https://github.com/nix-community/nixos-modules-contrib).
- Notable Files Removed:
nix/adhoc-cloud-vm.nix(#1303β https://github.com/NixOS/nixops/pull/1303,#1312β https://github.com/NixOS/nixops/pull/1312) β the included behavior was not targeted to any specific use case or generic to support all cloud VMs.nix/auto-luks.nix(#1297β https://github.com/NixOS/nixops/pull/1297,#1312β https://github.com/NixOS/nixops/pull/1312) β the module is now nixos-modules-contrib (https://github.com/nix-community/nixos-modules-contrib), since its behavior was not specific to NixOps, and outside of the core feature set of NixOps.nix/auto-raid0.nix(#1299β https://github.com/NixOS/nixops/pull/1299,#1312β https://github.com/NixOS/nixops/pull/1312) β the module is now nixos-modules-contrib (https://github.com/nix-community/nixos-modules-contrib), since its behavior was not specific to NixOps, and outside of the core feature set of NixOps.nixops/data/nixos-infect(#1305β https://github.com/NixOS/nixops/pull/1305,#1312β https://github.com/NixOS/nixops/pull/1312) β plugins needing nixos-infect should include it themselves.
- Too many other features/fixes to count. See
#1242(https://github.com/NixOS/nixops/issues/1242) for more insight.
This release has contributions by: Aaron Hall, Adam HΓΆse, Adam Mccullough, Amine Chikhaoui, Andreas Rammhold, Andrey Golovizin, Antoine Eiche, Benjamin Hipple, Bernardo Meurer, Chaker Benhamed, Cole Helbling, David Kleuker, DavΓΓ° Steinn Geirsson, Domen KoΕΎar, Eelco Dolstra, Florian Klink, Graham Christensen, Jean-baptiste Musso, Jeff Slight, Jleeuwes, John A. Lotoski, John Lotoski, Joseph Lucas, Lenz Weber, Lorenzo Manacorda, Luke Bentley-fox, Matthieu Coudron, Maximilian Bosch, Mazen.homrane, Michael Fellinger, Nathan Van Doorn, Niklas HambΓΌchen, Pascal Wittmann, Pixelkind, Psyanticy, Regnat, Robert Hensing, Ryan Mulligan, Samuel Leathers, Shay Bergmann, Tanner Doshier, Tewfik Ghariani, Tobias Pflug, Tom Bereknyei, Tomasz Rybarczyk, Victor Multun Collod, Vika, Vladimir Serov, Wout Mertens, Yc.s. π absolute legends, every single one
πΈ Release 1.7 (April 17, 2019)
General
- Mitigation for the
sshStrictHostKeyChecking=noissue. - Fix
nixops info --plainoutput. - Documentation fixes: add AWS VPC resources and fix some outdated command outputs.
- Addition of Hashicorp's Vault AppRole resource.
AWS
- Add more auto retries to api calls to prevent eventual consistency issues.
- Fix
nixops checkwith NVMe devices. - Route53: normalize DNS hostname.
- S3: support bucket lifecycle configuration as well as versioning.
- S3: introduce
persistOnDestroyfor S3 buckets which allows keeping the bucket during a destroy for later usage. - Fix backup-status output when backup is performed on a subset of devices.
Datadog
- add tags for Datadog monitors
GCE
- Fix machines being leaked when running destroy after a stop operation.
- make sure the machine exists before attempting a destroy.
Hetzner
- Remove usage of local commands for network configuration.
β οΈ Warning β note that this is incompatible with NixOS versions prior to 18.03. See release-notes: https://nixos.org/nixos/manual/release-notes.html#sec-release-18.03-notable-changes π
VirtualBox
- added NixOS 18.09/19.03 images.
- handle deleted VMs from outside NixOps.
This release has contributions from Amine Chikhaoui, Assassinkin, aszlig, Aymen Memni, Chaker Benhamed, Chawki Cheikch, David Kleuker, Domen KoΕΎar, Dorra Hadrich, dzanot, Eelco Dolstra, JΓΆrg Thalheim, Kosyrev Serge, Max Wilson, Michael Bishop, Niklas HambΓΌchen, Pierre Bourdon, PsyanticY, Robert Hensing. π«Ά
π¦ Release 1.6.1 (Sep 14, 2018)
General
- Fix the deployment of machines with a large number of keys.
- Show exit code of configuration activation script, when it is non-zero.
- Ignore evaluation errors in destroy and delete operations.
- Removed top-level Exception catch-all.
- Minor bugfixes.
AWS
- Automatically retry certain API calls.
- Fixed deployment errors when
deployment.route53.hostNamecontains uppercase letters. - Support for GCE routes.
- Support attaching NVMe disks.
GCE
- Add labels for GCE volumes and snapshots.
- Add option to enable IP forwarding.
VirtualBox
- Use images from nixpkgs if available.
This release has contributions from Amine Chikhaoui, aszlig, Aymen Memni, Chaker Benhamed, Domen KoΕΎar, Eelco Dolstra, Justin Humm, Michael Bishop, Niklas HambΓΌchen, Rob Vermaas, Sergei Khoma. π
π Release 1.6 (Mar 28, 2018)
General
- JSON output option for show-option command.
- Added experimental
--show-planto deploy command. Only works for VPC resources currently.
Backend: libvirtd
- Added support for custom kernel/initrd/cmdline, for easier kernel testing/developing.
- Fail early when defining domain.
- Support NixOS 18.03
Backend: AWS/EC2
- Allow changing security groups for instances that were deployed with a default VPC (no explicit
subnetId/vpc) - Make sure EC2 key pair not destroyed when it is in use, instead produce error.
- Support for separate Route53 resources.
- Support CloudWatch metrics and alarms.
- Support updating IAM instance profile of an existing instance.
- Support VPC resources.
- RDS: allow multiple security groups.
- Allow S3 buckets to be configured as websites.
- Fix issue where S3 bucket policy was only set on initial deploy.
Backend: Datadog
- Support sending start/finish of deploy and destroy events.
- Support setting downtime during deployment.
Backend: Azure
- Fix Azure access instructions.
Backend: Google Compute
- Add support for labelling GCE instances
- Minor fixes to make GCE backend more consistent with backends such as EC2.
- Fix attaching existing volumes to instances.
- Implemented
show-physical --backupfor GCE, similar to EC2. - Prevent
google-instance-setupservice from replacing the host key deployed by NixOps. - Allow instances to be created inside VPC subnets.
This release has contributions from Adam Scott, Amine Chikhaoui, Anthony Cowley, Brian Olsen, Daniel Kuehn, David McFarland, Domen KoΕΎar, Eelco Dolstra, Glenn Searby, Graham Christensen, Masato Yonekawa, Maarten Hoogendoorn, Matthieu Coudron, Maximilian Bosch, Michael Bishop, Niklas HambΓΌchen, Oussama Elkaceh, Pierre-Γtienne Meunier, Peter Jones, Rob Vermaas, Samuel Leathers, Shea Levy, Tomasz CzyΕΌ, Vaibhav Sagar. π
π Release 1.5.2 (Oct 29, 2017)
General
- This release has various minor bug and documentation fixes.
#703: don't ask for known host if file doesn't exist.- Deprecated
--evaluate-onlyfor--dry-run.
Backend: libvirtd
- Added
domainTypeoption. - Make the libvirt images readable only by their owner/group.
- Create "persistent" instead of "transient" domains, this ensures that nixops deployments/VMs survive a reboot.
- Stop using disk backing file and use self contained images.
Backend: EC2
#652, allowsecurityGroupsof Elastic File System mount target to be set.#709: allow Elastic IP resource for security groupsourceIPattribute.
Backend: Azure
- Use Azure images from nixpkgs, if they are available.
Backend: Google Compute
- Use Google Compute images from nixpkgs, if they are available.
This release has contributions from Andreas Rammhold, BjΓΈrn Forsman, Chris Van Vranken, Corbin, Daniel Ehlers, Domen KoΕΎar, Johannes Bornhold, John M. Harris, Jr, Kevin Quick, Kosyrev Serge, Marius Bergmann, Nadrieril, Rob Vermaas, Vlad Ki. β
π Release 1.5.1 (Jul 5, 2017)
General
- This release has various minor bug and documentation fixes.
Backend: None
#661: Addeddeployment.keys.*.keyFileoption to provide keys from local files, rather than from text literals.#664: Addeddeployment.keys.*.destDiranddeployment.keys.*.pathoptions to give more control over where the deployment keys are stored on the deployed machine.
Backend: Datadog
- Show URL for dashboards and timeboards in info output.
Backend: Hetzner
- Added option to disable creation of sub-accounts.
Backend: Google Compute
- Added option to set service account for an instance.
- Added option to use preemptible option when creating an instance.
Backend: Digital Ocean
- Added option to support IPv6 on Digital Ocean.
shoutout szn, bestie β this release has contributions from Albert Peschar, Amine Chikhaoui, aszlig, Clemens Fruhwirth, Domen KoΕΎar, Drew Hess, Eelco Dolstra, Igor Pashev, Johannes Bornhold, Kosyrev Serge, Leon Isenberg, Maarten Hoogendoorn, Nadrieril Feneanar, Niklas HambΓΌchen, Philip Patsch, Rob Vermaas, Sven Slootweg. literally every single one of them ate π
π Release 1.5 (Feb 16, 2017)
- General β¨
- Various minor documentation and bug fixes
#508: the SSH tunnels implementation got a whole rewrite so it usesiprouteinstead ofnetttoolsβ glow up π#400: key ownership is now handled after user/group creation (order matters, bestie)#216: added the--keep-daysoption, for cleaning up backups π#594: the NixOps statefile is created with stricter permissions now β safety slay- Uses
types.submoduleinstead of the deprecatedtypes.optionSet #566: support for settingdeployment.hasFastConnection- support for
nixops deploy --evaluate-only
- Backend: None
- creates
/etc/hosts
- creates
- Backend: Amazon Web Services π₯
- support for Elastic File Systems
- support for the latest EBS volume types
- support for Simple Notification Service
- support for Cloudwatch Logs resources
- support for loading credentials from
~/.aws/credentials(the AWS default) - HVM is now the default virtualization type (all the new instance types are HVM, iykyk)
#550: fixed that sporadicError binding parameter 0 - probably unsupported typeerror β she's gone π
- Backend: Datadog
- support for provisioning Datadog Monitors
- support for provisioning Datadog Dashboards
- Backend: Hetzner
#564: binary cache substitutions were broken by certificate errors β fixed
- Backend: VirtualBox
- support for dots in machine names
- added the
vcpuoption
- Backend: Libvirtd
- documentation typo fixes (we love a proofread era πΈ)
- Backend: Digital Ocean
- initial support for Digital Ocean to deploy machines β baby's first steps π¦
This release has contributions from Amine Chikhaoui, Anders Papitto, aszlig, Aycan iRiCAN, Christian Kauhaus, Corbin Simpson, Domen KoΕΎar, Eelco Dolstra, Evgeny Egorochkin, Igor Pashev, Maarten Hoogendoorn, Nathan Zadoks, Pascal Wittmann, Renzo Carbonaram, Rob Vermaas, Ruslan Babayev, Susan Potter and Danylo Hlynskyi. π«Ά
π Release 1.4 (Jul 11, 2016)
- General β¨
- added the
show-argumentscommand, so you can query thenixopsarguments that are defined in the nix expressions - added the
--dry-activateoption to thedeploycommand, so you can peek at which services will be stopped/started/restarted π - added the
--fallbackoption to thedeploycommand, matching the same flag onnix-build - added the
--coresoption to thedeploycommand, also matching the same flag onnix-build
- added the
- Backend: None
- (nothing here, iconique silence π)
- Amazon EC2
- uses
hvm-s3AMIs when appropriate - the EBS optimized flag can now be changed (this needs
--allow-reboot, just so you know) - you can now recover from a spot instance kill when you're using an external volume defined as a resource (
resources.ebsVolumes) - when disassociating an elastic IP, it now checks that the current instance is the one actually associated with it, in case somebody else has 'stolen' the elastic IP π rude
- uses a generated list for
deployment.ec2.physicalProperties, based on the Amazon Pricing listing - the EC2 AMI registry has been moved to the nixpkgs repository
- you can set a timeout on spot instance creation
- you can update security groups on running instances in a VPC
- support for
x1instances π₯
- uses
- Backend: Azure
- brand new Azure Cloud backend, contributed by Evgeny Egorochkin π
- Backend: VirtualBox
- respects
deployment.virtualbox.disks.*.sizefor images with abaseImage - you can override the VirtualBox base image size for
disk1
- respects
- Libvirt
- improved logging messages
#345: usesqemu-system-x86_64instead ofqemu-kvmso non-NixOS is supported- added the
extraDomainXMLNixOS option - added the
extraDevicesXMLNixOS option - added the
vcpuNixOS option
This release has contributions from Amine Chikhaoui, aszlig, Cireo, Domen KoΕΎar, Eelco Dolstra, Eric Sagnes, Falco Peijnenburg, Graham Christensen, Kevin Cox, Kirill Boltaev, Mathias Schreck, Michael Weiss, Brian Zach Abe, Pablo Costa, Peter Hoeg, Renzo Carbonara, Rob Vermaas, Ryan Artecona, Tobias Pflug, Tom Hunger, Vesa Kaihlavirta, Danylo Hlynskyi. π
π Release 1.3.1 (January 14, 2016)
- General β¨
#340: thetoo long for Unix domain socketerror#335: uses the correct port when setting up an SSH tunnel#336: added support for non-machine IP resources in/etc/hosts- fixed how
system.stateVersionis determined ssh_util: reconnects when the SSH master socket is dead#379: removed the reference to thejobsattribute in NixOS
- Backend: None
- passes
deployment.targetPorttosshfor none backend #361: doesn't use_ssh_private_keyif its corresponding public key hasn't been deployed yet
- passes
- Amazon EC2
- you can specify
assumeRolePolicyfor IAM roles - added the
vpcIdoption to EC2 security group resources - VPC security groups can refer to sec. group names (within the same sec. group) as well as group ids
- stops VPC calls from being made when only security group ids are being used (instead of names)
- uses the correct credentials for VPC API calls
- fixed
creating EC2 instance (... region βNoneβ)when recreating a missing instance - you can keep volumes while destroying a deployment
- you can specify
- VirtualBox
#359: changedsbin/mount.vboxsftobin/mount.vboxsf
- Hetzner
#349: doesn't create/root/.ssh/authorized_keys#348: fixup and refactor of the Hetzner backend testshetzner-bootstrap: fixes wrapping Nix inside chroothetzner-bootstrap: you can now easily enter the chroot
- Libvirt
#374: added headless mode#374: uses a more reliable method to retrieve the IP address#374: nicer error message for a missing images dir#374: you can specify xml for devices
This release has contributions from aszlig, Bas van Dijk, Domen KoΕΎar, Eelco Dolstra, Kevin Cox, Paul Liu, Robin Gloster, Rob Vermaas, Russell O'Connor, Tristan Helmich and Yves ParΓ¨s (Ywen). πΈ
π Release 1.3 (September 28, 2015)
- General β¨
- NixOps now requires NixOS 14.12 and up β οΈ (so check that before you come crying to me)
- machines in a NixOps network now have access to the deployment name, uuid and its arguments, via the
deployment.name,deployment.uuidanddeployment.argumentsoptions - support for
<...>paths in network spec filenames, e.g. you can do:
nixops create '<nixops/templates/container.nix>'
- support for
username@machinefornixops scp
- Amazon EC2
- support for the latest EC2 instance types, including
t2andc4instances - support for Amazon EBS SSD disks
- instances can be placed in an EC2 placement group, which lets instances be grouped in a low-latency 10 Gbps network π₯
- you can start EC2 instances in a VPC subnet
- more robust handling of spot instance creation
- support for setting bucket policies on S3 buckets created by NixOps
- Route53 support now uses a CNAME to the public DNS hostname instead of an A record to the public IP address
- support for Amazon RDS instances
- support for the latest EC2 instance types, including
- Google Cloud
- new backend for Google Cloud Platform. It includes support for the following resources:
- VirtualBox
- VirtualBox 5.0 is required for the VirtualBox backend β οΈ
- NixOS container
- new backend for NixOS containers π
- Libvirt
- new backend for libvirt using QEMU/KVM
This release has contributions from Andreas Herrmann, Andrew Murray, aszlig, Aycan iRiCAN, Bas van Dijk, Ben Moseley, BjΓΈrn Forsman, Boris Sukholitko, Bruce Adams, Chris Forno, Dan Steeves, David Guibert, Domen KoΕΎar, Eelco Dolstra, Evgeny Egorochkin, Leroy Hopson, Michael Alyn Miller, Michael Fellinger, Ossi Herrala, Rene Donner, Rickard Nilsson, Rob Vermaas, Russell O'Connor, Shea Levy, Tomasz Kontusz, Tom Hunger, Trenton Strong, Trent Strong, Vladimir Kirillov, William Roe. π
π Release 1.2 (April 30, 2014)
- General β¨
- NixOps now requires NixOS 13.10 and up β οΈ
- added the
--alloption tonixops destroy,nixops deleteandnixops ssh-for-each - the
-doption now matches based on prefix for convenience, when the specified uuid/id isn't found - resources can now be accessed via direct reference, i.e. you can use
securityGroups = [ resources.ec2SecurityGroups.foo ];in stead ofsecurityGroups = [ resources.ec2SecurityGroups.foo.name ]; - the default value of
deployment.storeKeysOnMachinechanged tofalse, which is the more secure option π β but heads up: this can prevent an unattended reboot from finishing, because keys will need to be pushed to the machine. so like, know that before you set it
- Amazon EC2
- support for provisioning elastic IP addresses
- support for provisioning EC2 security groups
- support for all HVM instance types
- support for the
ap-southeast-1region - better handling of errors when pushing Route53 records
- support for using ARNs to apply instance profiles to EC2 instances, which allows cross-account API access
- the base HVM image was updated to allow using all ephemeral devices
- the instance ID is now available in nix through the
deployment.ec2.instanceIdoption, set by nixops - support for independent provisioning of EBS volumes. before this, EBS volumes could only be created as part of an EC2 instance, which meant their lifetime was tied to the instance and they couldn't be managed separately. now they can be provisioned independently, e.g.:
resources.ebsVolumes.bigdata =
{ name = "My Big Fat Data";
region = "eu-west-1";
zone = "eu-west-1a";
accessKeyId = "...";
size = 1000;
};
- to allow cross-account API access, the
deployment.ec2.instanceProfileoption can now be set to either a name (the previous behaviour) or an Amazon Resource Name (ARN) of the instance profile you want to apply
- Hetzner
- always hard resets when destroying a machine
- support for Hetzner vServers
- the root password is disabled by default
- fixed hard reset for rebooting into rescue mode. this one's extra useful if you have a dead server and want to put it in rescue mode β now you can just run:
nixops reboot --hard --rescue --include=deadmachine
- VirtualBox
- requires VirtualBox >= 4.3.0 β οΈ
- support for shared folders in VirtualBox β you can mount a host folder on the guest by setting the
deployment.virtualbox.sharedFoldersoption π
- Allow destroy if the VM is gone already
This release has contributions from aszlig, Corey O'Connor, Domen KoΕΎar, Eelco Dolstra, Michael Stone, Oliver Charles, Rickard Nilsson, Rob Vermaas, Shea Levy and Vladimir Kirillov.
π Release 1.1.1 (October 2, 2013)
Okay so this one is a lil minor bugfix release, but it still ate π
- Added a command-line option
--include-keysso you can import SSH public host keys of the machines that are gonna be imported into the user's.ssh/known_hosts. Handy, no cap. - Fixed a bug that was literally blocking you from switching the
deployment.storeKeysOnMachineoption value. Rude behaviour, now gone. - On non-EC2 systems, NixOps now generates ECDSA SSH host key pairs instead of DSA. Moving on up β¨
- VirtualBox deployments use generated SSH host key pairs.
- For all machines where
nixopsgenerates an SSH host key pair, it adds the SSH public host key to theknown_hostsconfiguration of every machine in the network. Everyone gets to know everyone π«Ά - For EC2 deployments, if the nixops expression specifies a set of security groups for a machine that's different from the security groups already applied to the existing machine, you get a warning that the change cannot be made. It's giving "we can't do that, bestie" π
- For EC2 deployments, disks that aren't supposed to be attached to the machine are detached only after system activation has been completed. Before this, it happened before β which could lead to volumes not being able to detach without needing to stop the machine. π
- Added a command-line option
--repairas a convenient way to pass this option (which allows repairing of broken or changed paths in the nix store) tonix-buildcalls thatnixopsperforms.
Heads up: --repair only works in nix setups that run without the nix daemon. Important, fr fr.
This release has contributions from aszlig, Ricardo Correia, Eelco Dolstra, Rob Vermaas.
π¦ Release 1.1 (September 9, 2013)
- Backend for Hetzner <http://hetzner.de>, a German data center provider. More information and a demo video can be found here <https://github.com/NixOS/nixops/pull/119>. Iconic.
- When using the
deployment.keys.*options, the keys in/run/keysare now created with mode600. Locked down π₯ - Fixed a bug where the EBS snapshots name tag was overridden by the instance name tag. Not the main character energy we wanted.
- The
nixopsexecutable now has the default OpenSSH from nixpkgs in itsPATHby default, to work around issues with left-over SSH master connections on older versions of OpenSSH β like the version installed by default on CentOS. We love a workaround π - A new resource type has been introduced to generate sets of SSH public/private keys. Slay.
- Support for spot instances in the EC2 backend. By specifying the
deployment.ec2.spotInstancePriceoption for a machine, you can set the spot instance price in cents. NixOps will wait 10 minutes for a spot instance to be fulfilled β and if not, then it errors out for that machine. Tick tock β°
π Release 1.0.1 (July 11, 2013)
This is a minor bugfix release. Short and sweet.
- Reduce parallelism for running EC2 backups, to prevent hammering the AWS API in case of many disks. Be nice to the API, bestie.
- Propagate the instance tags to the EBS volumes (except for the
Nametag, which is overridden with a detailed description of the volume and its use).
π Release 1.0 (June 18, 2013)
Initial release. The origin story π
- Index <>
- Module Index <>
- Search Page <>
π Author
NixOps Contributors
π Copyright
2020, NixOps Contributors
And that's the whole thing, bestie! You just read NIXOPS(1) β dated Jan 02, 1980 in the footer, which is a whole vibe β written by the NixOps Contributors, with copyright 2020, NixOps Contributors. Go forth and deploy β¨ππ¦
π¦ where this page comes from
- nixos 26.05: nixops 2.0.0-unstable-2025-12-28
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms