diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000000000000000000000000000000000000..3f7ee838224159646383c45c5b0fa64705abbb57
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,7 @@
+use flake
+
+use_flake() {
+  watch_file flake.nix
+  watch_file flake.lock
+  eval "$(nix print-dev-env --profile "$(direnv_layout_dir)/flake-profile")"
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..20cdc74b890575bb12037ab91e5af14132c0efb3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.direnv/
+.history
diff --git a/README.md b/README.md
index f67f1b1c08443cfa5bd089cdebd52ca282d5c0e7..d39524eb4bd5adb2d7a0ed28ccbf5e24c6514c80 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,18 @@ pip:
 1. Enter virtualenv: `source my-venv-directory/bin/activate`
 1. Install ansible: `pip install ansible`
 
+#### Using nix
+
+Use `nix-shell` or `nix develop` to use ansible.
+
+Update to newer nixpkgs version (check functionality and add a commit afterwards):
+
+`nix flake update --recreate-lock-file --update-input nixpkgs`
+
+#### Using direnv
+
+Run `mkdir .direnv && direnv allow .` to enable direnv integration with nix flakes.
+
 ### SSH Aliases
 
 Some hosts are only reachable through a jumphost, e.g. Containers or VMs on a
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000000000000000000000000000000000000..2cc10a02550caa5d3c729c01f727e00741fcf4d6
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,43 @@
+{
+  "nodes": {
+    "flake-utils": {
+      "locked": {
+        "lastModified": 1609246779,
+        "narHash": "sha256-eq6ZXE/VWo3EMC65jmIT6H/rrUc9UWOWVujkzav025k=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "08c7ad4a0844adc4a7f9f5bb3beae482e789afa4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1609187327,
+        "narHash": "sha256-6lCwWpGpZxbSYclryv4ixsxxbISe7HuLyyQnGWCC8ZQ=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "e065200fc90175a8f6e50e76ef10a48786126e1c",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-20.09",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nixpkgs": "nixpkgs"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000000000000000000000000000000000000..0565344cfde347e2ade89fdce6d5383448145d6e
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,19 @@
+{
+  description = "Freifunk Stuttgart - ansible";
+
+  # To update all inputs:
+  # $ nix flake update --recreate-lock-file
+  inputs = {
+    flake-utils.url = "github:numtide/flake-utils";
+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-20.09";
+  };
+
+  outputs = { self, nixpkgs, flake-utils }:
+    flake-utils.lib.eachDefaultSystem
+      (system:
+        let pkgs = nixpkgs.legacyPackages.${system}; in
+        {
+          devShell = import ./shell.nix { inherit pkgs; };
+        }
+      );
+}
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000000000000000000000000000000000000..6ab9c17e098e1c1577af82e6b1970aa281a69fe9
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,22 @@
+let
+  lock = builtins.fromJSON (builtins.readFile ./flake.lock);
+in
+{
+ pkgs ? import (fetchTarball {
+   url = "https://github.com/NixOS/nixpkgs/archive/${lock.nodes.nixpkgs.locked.rev}.tar.gz";
+   sha256 = lock.nodes.nixpkgs.locked.narHash;
+ }) { }
+}:
+
+with pkgs;
+
+mkShell {
+  name = "ansible-shell";
+  buildInputs = [
+    ansible_2_10
+    ansible-lint
+    git-crypt
+    sshpass
+  ];
+  HISTFILE = "${toString ./.}/.history";
+}