A lot of clean up

Signed-off-by: Magic_RB <magic_rb@redalder.org>
This commit is contained in:
Magic_RB 2021-05-02 15:59:38 +02:00
parent 04b5465e95
commit 776a450903
No known key found for this signature in database
GPG key ID: 08D5287CC5DDCA0E
30 changed files with 67 additions and 1593 deletions

View file

@ -1,10 +0,0 @@
images = csi-driver-nfs gitea klippy-moonraker postgresql
all: $(images) bin
bin:
mkdir -p bin
%:
nix build .#dockerImages.$@ --out-link bin/$@.tar.gz
docker load < bin/$@.tar.gz

View file

@ -1,28 +1,3 @@
#+OPTIONS: toc:nil #+OPTIONS: toc:nil
* Red Alder systems * Red Alder systems
** Overview
This repository contains Docker images built from [[https://github.com/NixOS/nixpkgs][Nixpkgs]] and custom Nix packages created by Red Alder. The Docker
images can be accessed with =systems.dockerImages.<imageName>= and the packages are accessible in a format similar to
Flakes. Meaning =systems.flakes.<packageName>=, contains the outputs of a Flake which contains the package and a
NixOS module if applicable, for example =systems.flakes.klippy.defaultPackage."x86_64-linux"= and
=systems.flakes.moonraker.nixosModules=. Even though the Nix packages are almost Flakes, this repository is
completely pure.
** Current Contents
*** Docker Images
While this repository does contain, what I'd consider functional and well made images, I must warn you that they are
far from finished, bug free or stable. If you wish to use them in production, consider this your warning. They
shouldn't delete your data, but I can't guarantee anything. So good luck!
- [[./docker/csi-driver-nfs][csi-driver-nfs]]
- [[./docker/klippy-moonraker][klippy-moonraker]]
- [[./docker/postgresql][postgresql]]
- [[./docker/gitea][gitea]]
*** Nix Packages
- [[./nix-packages/klippy][klippy]]
- [[./nix-packages/mainsail][mainsail]]
- [[./nix-packages/moonraker][moonraker]]

View file

@ -1,104 +0,0 @@
set -u +e
## Args
# - vars - a space separated list of variables
save_env() {
local vars="$1"
for var in $vars ; do
echo "$var=${!var}"
done
}
make_opt() {
local name="$1"
echo "_${name,,}"
}
## Args
# - var - variable name, for example PG_DATA
# - default - default value
default_opt() {
local var="$1"
local default="$2"
local parsed="$(make_opt $var)"
local result="${!var:-$default}"
eval "$parsed=\"$result\""
}
## Args
# - var - variable name, for example PG_DATA
# - error - error message
required_opt() {
local var="$1"
local error="$2"
if [[ ! -z "${!var:-}" ]] ; then
local parsed="$(make_opt $var)"
eval "$parsed=\"\$$var\""
else
echo_exit "$error"
fi
}
## Args
# - path - path to the inode to check
# - uid - desired uid
# - gid - desired gid
check_owner() {
local path="$1"
local desired_uid="$2"
local desired_gid="$3"
uid=$($_prog_busybox/bin/stat -c '%u' $path || \
echo_exit "Failed to get uid of $path")
gid=$($_prog_busybox/bin/stat -c '%g' $path || \
echo_exit "Failed to get gid of $path")
[[ $uid == $desired_uid ]] && [[ $gid == $desired_gid ]] || \
echo_exit "Invalid owner for \`$path\`, has $uid:$gid wanted $desired_uid:$desired_gid"
}
## Args
# - path - path to the directory to create
# - uid - desired uid
# - gid - desired gid
mkdir_chown() {
path="$1"
uid="$2"
gid="$3"
[[ ! -f "$path" ]] \
&& $_prog_busybox/bin/mkdir -p "$path" && $_prog_busybox/bin/chown "$uid:$gid" "$path"
}
## Args
# - uid - currently set uid
check_root() {
local uid="$1"
[[ "$uid" = "0" ]] \
&& echo_exit "UID is set to $uid, which would cause an infinite loop!"
}
## Args
# - message - message to exit with
echo_exit() {
local msg="$1 Exiting..."
echo $msg
exit 1
}
## Args
# - ca-certificates.crt - nix path to ca-certificates.crt
create_ssl_certs() {
local ca_certificates="$1/etc/ssl/certs/ca-bundle.crt"
$_prog_busybox/bin/mkdir -p /etc/ssl/certs
$_prog_busybox/bin/ln $ca_certificates /etc/ssl/certs/ca-bundle.crt
$_prog_busybox/bin/ln $ca_certificates /etc/ssl/certs/ca-certificates.crt
}

View file

@ -1,26 +0,0 @@
{ pkgs, nixpkgs, ... }@inputs:
let
csi-driver-nfs = pkgs.buildGoModule {
name = "csi-driver-nfs";
version = "2.0";
vendorSha256 = null;
doCheck = false;
src = inputs.csi-driver-nfs;
};
init = with pkgs; pkgs.writeShellScriptBin "init" ''
export "PATH=${busybox}/bin:$PATH"
echo $PATH
exec ${csi-driver-nfs}/bin/nfsplugin $@
'';
in
pkgs.dockerTools.buildLayeredImage {
name = "csi-driver-nfs";
tag = "latest";
config = {
Entrypoint = [ "${init}/bin/init" ];
};
}

View file

@ -1,49 +0,0 @@
{ system, nixpkgs, ... }:
let
overlay = self: super:
{
openssh = super.openssh.override {
withKerberos = false;
withFIDO = false;
};
git = super.git.override {
perlSupport = false;
nlsSupport = false;
withManual = false;
guiSupport = false;
pythonSupport = false;
withpcre2 = false;
sendEmailSupport = false;
};
gitea = super.gitea.override {
pamSupport = false;
};
# glibc = super.glibc.override {
# withLinuxHeaders = false;
# };
};
pkgs = (import nixpkgs { inherit system; overlays = [ overlay ]; });#.pkgsMusl;
bashLib = ../bash-lib;
init = pkgs.writeShellScriptBin "init" (builtins.readFile ./init);
conf = pkgs.writeText "conf" ''
_prog_busybox="${pkgs.busybox}"
_prog_sudo="${pkgs.sudo}"
_prog_bashlib="${bashLib}"
_prog_bash="${pkgs.bash}"
_prog_gitea="${pkgs.gitea}"
_conf_user_uid="5000"
_conf_user_gid="5000"
_conf_data="/data/gitea"
_conf_cacert="${pkgs.cacert}"
'';
in
# conf
pkgs.dockerTools.buildLayeredImage {
name = "gitea";
tag = "latest";
config = {
Entrypoint = [ "${init}/bin/init" "${conf}" ];
};
}

View file

@ -1,10 +0,0 @@
version: "3.3" # optional since v1.27.0
services:
gitea:
image: gitea:latest
ports:
- "3000:3000"
volumes:
- type: bind
source: $PWD/app.ini
target: /app.ini

View file

@ -1,56 +0,0 @@
# -*- mode: shell-script; -*-
if [[ ! -f /env ]]
then
conf=$1 ; shift 1
source $conf
else
source /env || \
echo_exit "Failed to source env!"
source $conf
fi
# shellcheck source=/../../bash-lib/main.bash
source $_prog_bashlib/main.bash
# if [[ $($_prog_busybox/bin/id -u) = 0 ]] ; then
$_prog_busybox/bin/cat << EOF
### Gitea Nix Image Manual
##
## USER_UID ? $_conf_user_uid - default user id
## USER_GID ? $_conf_user_gid - default group id
### You must place a \`app.ini\` at \`/app.ini\`
### Volume Mounts
##
## - $_conf_data - Gitea base data folder
EOF
default_opt USER_UID "$_conf_user_uid"
default_opt USER_GID "$_conf_user_gid"
$_prog_busybox/bin/cat << EOF
### Starting with options:
## USER_UID = "$_user_uid"
## USER_GID = "$_user_gid"
EOF
(
set -e
echo "gitea:x:$_user_uid:$_user_gid:Gitea:$_conf_data:$_prog_bash/bin/bash" > /etc/passwd
echo "gitea:x:$_user_gid:" > /etc/group
) || echo_exit "Failed to create user and group!"
[[ ! -d $_conf_data ]] && mkdir_chown $_conf_data "$_user_uid" "$_user_gid"
mkdir_chown /tmp "$_user_uid" "$_user_gid"
$_prog_busybox/bin/mkdir -p /usr/bin
$_prog_busybox/bin/ln -s $_prog_busybox/bin/env /usr/bin/env
create_ssl_certs $_conf_cacert
echo "Starting Gitea!"
exec $_prog_busybox/bin/su gitea -c "$_prog_gitea/bin/gitea -c /app.ini $@"
# fi

View file

@ -1,103 +0,0 @@
{ pkgs, nixpkgs, ... }:
let
init = let
klippy_input_tty_default = "/tmp/printer";
klippy_api_server_default = "/tmp/klippy_uds";
moonraker_logfile_default = "/moonraker.log";
in pkgs.writeShellScriptBin "init" ''
#!${pkgs.bash}
##
## KLIPPY_INPUT_TTY ? ${klippy_input_tty_default} - input tty path for Klippy
## KLIPPY_API_SERVER ? ${klippy_api_server_default} - api server path for Klippy
## [ KLIPPY_VERBOSE ] - enable verbosity for Klippy
## [ KLIPPY_DICTIONARY ] - specifies dictionary path for Klippy
## [ KLIPPY_LOGFILE ] - enable logging and specify log file path for Klippy
## KLIPPY_CONFIG - specifies config file path for Klippy
##
## MOONRAKER_CONFIG - specifies config file path for Moonraker
## MOONRAKER_LOGFILE ? ${moonraker_logfile_default} - specifies log file path for Moonraker
##
### Recommended volumes (many directories which exist in normal Docker containers, do not exist in this one)
##
## Note: paths are in /root, due to moonraker refusing to use paths that are not in $HOME or /etc/moonraker
## - /root/virtual_sdcard - used to store gcode files for printing
## - /root/config/klippy - place your config file for klippy here
## - /root/config/moonraker
if [[ ! -z "$KLIPPY_INPUT_TTY" ]] ; then
_klippy_input_tty="$KLIPPY_INPUT_TTY"
else
_klippy_input_tty="${klippy_input_tty_default}"
fi
if [[ ! -z "$KLIPPY_API_SERVER" ]] ; then
_klippy_api_server="$KLIPPY_API_SERVER"
else
_klippy_api_server="${klippy_api_server_default}"
fi
_klippy_verbose="$KLIPPY_VERBOSE"
_klippy_dictionary="$KLIPPY_DICTIONARY"
_klippy_logfile="$KLIPPY_LOGFILE"
if [[ ! -z "$KLIPPY_CONFIG" ]] ; then
if [[ -f "$MOONRAKER_CONFIG" ]] ; then
_klippy_config="$KLIPPY_CONFIG"
else
echo "File \"$KLIPPY_CONFIG\" specified in \`KLIPYY_CONFIG\` does not exist!" ; exit 1
fi
else
echo 'You must specify the `KLIPPY_CONFIG` parameter!' ; exit 1
fi
if [[ ! -z "$MOONRAKER_CONFIG" ]] ; then
if [[ -f "$MOONRAKER_CONFIG" ]] ; then
_moonraker_config="$MOONRAKER_CONFIG"
else
echo "File \"$MOONRAKER_CONFIG\" specified in \`MOONRAKER_CONFIG\' does not exist!" ; exit 1
fi
else
echo 'You must specify the `MOONRAKER_CONFIG` parameter!' ; exit 1
fi
if [[ ! -z "$MOONRAKER_LOGFILE" ]] ; then
_moonraker_logfile="$MOONRAKER_LOGFILE"
else
_moonraker_logfile="${moonraker_logfile_default}";
fi
${pkgs.busybox}/bin/mkdir -p \
/usr/bin \
/tmp \
/root/{virtual_sdcard,config/{klippy,moonraker}}
${pkgs.busybox}/bin/ln -s ${pkgs.busybox}/bin/env /usr/bin/env
${pkgs.klippy}/bin/klippy \
--input-tty "$_klippy_input_tty" \
--api-server "$_klippy_api_server" \
$([[ ! -z "$_klippy_logfile" ]] && echo --logfile "$_klippy_logfile" || echo "") \
$([[ ! -z "$_klippy_verbose" ]] && echo -v || echo "") \
$([[ ! -z "$_klippy_dictionary" ]] && echo --dictionary "$_klippy_dictionary" || echo"") \
"$_klippy_config" &
klippy_pid=$!
${pkgs.moonraker}/bin/moonraker \
--configfile "$_moonraker_config" \
--logfile "$_moonraker_logfile" &
moonraker_pid=$!
wait "$moonraker_pid"
wait "$klippy_pid"
'';
in
pkgs.dockerTools.buildLayeredImage {
name = "klippy-moonraker";
tag = "latest";
config = {
Cmd = [ "${init}/bin/init" ];
};
}

View file

@ -1,26 +0,0 @@
{ pkgs, system, nixpkgs, nixpkgs-unstable, ... }:
let
bashLib = ../bash-lib;
init = pkgs.writeShellScriptBin "init" (builtins.readFile ./init);
conf = pkgs.writeText "conf" ''
_prog_busybox="${pkgs.busybox}"
_prog_bashlib="${bashLib}"
_prog_bash="${pkgs.bash}"
_prog_mariadb="${(import nixpkgs-unstable { inherit system; }).mariadb}"
_prog_nettools="${pkgs.nettools}"
_conf_user_uid="5000"
_conf_user_gid="5000"
_conf_data="/data/mariadb"
_file_mariadb_conf=${./mariadb.cnf}
'';
in
pkgs.dockerTools.buildLayeredImage {
name = "mariadb";
tag = "latest";
config = {
Entrypoint = [ "${init}/bin/init" "${conf}" ];
};
}

View file

@ -1,68 +0,0 @@
# -*- mode: shell-script; -*-
if [[ ! -f /env ]]
then
conf=$1 ; shift 1
source $conf
else
source /env || \
echo_exit "Failed to source env!"
source $conf
fi
source $_prog_bashlib/main.bash
if [[ $($_prog_busybox/bin/id -u) = 0 ]] ; then
$_prog_busybox/bin/cat <<EOF
### MariaDB Nix Image Manual
##
## USER_UID ? $_conf_user_uid - default user id
## USER_GID ? $_conf_user_gid - default group id
### Place additional config files in \`/etc/mysql/mariadb.conf.d\`
EOF
default_opt USER_UID "$_conf_user_uid"
default_opt USER_GID "$_conf_user_gid"
$_prog_busybox/bin/cat <<EOF
### Starting with options:
## USER_UID = "$_user_uid"
## USER_GID = "$_user_gid"
EOF
(
set -e
echo "mariadb:x:$_user_uid:$_user_gid:MariaDB:$_conf_data:$_prog_bash/bin/bash" > /etc/passwd
echo "mariadb:x:$_user_gid:" > /etc/group
) || echo_exit "Failed to create user and group!"
mkdir_chown /tmp "$_user_uid" "$_user_gid"
mkdir_chown /run/mysqld/ "$_user_uid" "$_user_gid"
mkdir_chown /etc/mysql 0 0
mkdir_chown /etc/mysql/mariadb.conf.d 0 0
$_prog_busybox/bin/ln -s "$_file_mariadb_conf" /etc/mysql/my.cnf
[[ ! -d $_conf_data ]] && (mkdir_chown $_conf_data "$_user_uid" "$_user_gid" || echo_exit "Failed to create \`$_conf_data\`")
if [[ ! -d $_conf_data/mysql ]]
then
PATH=$_prog_busybox/bin:$_prog_nettools/bin $_prog_mariadb/bin/mysql_install_db --user=mariadb --datadir=$_conf_data --defaults-file=/etc/mysql/my.cnf
fi
check_owner "$_conf_data" "$_user_uid" "$_user_gid"
save_env "_user_uid \
_user_gid \
conf
" > /env
check_root "$_user_uid"
exec $_prog_busybox/bin/su mariadb -c "$0 $@" || /
echo_exit "Failed to switch user!"
else
echo
echo "Starting MariaDB!"
$_prog_mariadb/bin/mysqld $@
fi

View file

@ -1,23 +0,0 @@
# The MariaDB configuration file
#
# The MariaDB/MySQL tools read configuration files in the following order:
# 1. "/etc/mysql/mariadb.cnf" (this file) to set global defaults,
# 2. "/etc/mysql/conf.d/*.cnf" to set global options.
# 3. "/etc/mysql/mariadb.conf.d/*.cnf" to set MariaDB-only options.
# 4. "~/.my.cnf" to set user-specific options.
#
# If the same option is defined multiple times, the last one will apply.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# This group is read both both by the client and the server
# use it for options that affect everything
#
[client-server]
datadir=/data/mariadb
# Import all .cnf files from configuration directory
!includedir /etc/mysql/mariadb.conf.d/

View file

@ -1,24 +0,0 @@
{ pkgs, system, nixpkgs, ... }:
let
bashLib = ../bash-lib;
init = pkgs.writeShellScriptBin "init" (builtins.readFile ./init);
conf = pkgs.writeText "conf" ''
_prog_busybox="${pkgs.busybox}"
_prog_bashlib="${bashLib}"
_prog_bash="${pkgs.bash}"
_prog_nix="${pkgs.nixFlakes}"
_conf_nixpkgs="${nixpkgs}"
_conf_cacert="${pkgs.cacert}"
_conf_user_uid="1000"
_conf_user_gid="1000"
'';
in
pkgs.dockerTools.buildLayeredImage {
name = "nix";
tag = "latest";
config = {
Entrypoint = [ "${init}/bin/init" "${conf}" ];
};
}

View file

@ -1,45 +0,0 @@
# -*- mode: shell-script; -*-
conf=$1 ; shift 1
source $conf
source $_prog_bashlib/main.bash
$_prog_busybox/bin/cat << EOF
### Nix Image Manual
# You may place a \`main.bash\` file at \`/main.bash\`, if it's there it will be executed, otherwise an interactive shell will be spawned
/nix/var/nix/db
/nix/var/nix/daemon-socket
/nix/store-host
EOF
(
set -e
echo "root:x:0:0:Nix:/:$_prog_bash/bin/bash" > /etc/passwd
echo "root:x:0:" > /etc/group
) || echo_exit "Failed to create user and group!"
mkdir_chown /tmp 0 0
if [[ -d "/nix/store-host" ]]
then
$_prog_busybox/bin/mount -t overlay overlay -o lowerdir=/nix/store:/nix/store-host /nix/store
export NIX_REMOTE=daemon
else
echo_exit "You must link the host nix store"
fi
export PATH=$_prog_bash/bin:$_prog_nix/bin:$_prog_busybox/bin \
NIX_PATH=nixpkgs=$_conf_nixpkgs \
NIX_SSL_CERT_FILE=$_conf_cacert/etc/ssl/certs/ca-bundle.crt
if [[ -f /main.bash ]]
then
$_prog_bash/bin/bash /main.bash $@
else
$_prog_bash/bin/bash
fi
# nix --experimental-features 'nix-command flakes' build github:edolstra/dwarffs

View file

@ -1,58 +1,15 @@
{ {
inputs = { inputs = {
nixpkgs.url = "nixpkgs"; nixpkgs.url = "nixpkgs";
nixpkgs-unstable.url = "nixpkgs-unstable";
csi-driver-nfs = { csi-driver-nfs = {
flake = false; flake = false;
url = "github:MagicRB/csi-driver-nfs"; url = "github:MagicRB/csi-driver-nfs";
}; };
klippy = {
url = "github:KevinOConnor/klipper?rev=e68cf08d15a985ecce7497b58408ee233dd54eb9";
flake = false;
};
moonraker = {
url = "github:MagicRB/moonraker?ref=master";
flake = false;
};
}; };
outputs = { self, nixpkgs, ... }@inputs: outputs = { self, nixpkgs, ... }@inputs:
let {
rlib =
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
in
import ./lib.nix { inherit system nixpkgs pkgs inputs; };
flakes = rlib.flakes ./nix-packages [
"klippy"
"mainsail"
"moonraker"
];
pkgs = rlib.pkgsWithFlakes flakes;
dockerImages = rlib.dockerImages pkgs ./docker [
"klippy-moonraker"
"postgresql"
"gitea"
"csi-driver-nfs"
"nix"
"mariadb"
];
containerTest = let
all-modules = import <nixpkgs/nixos/modules/module-list.nix>;
custom-module = rec {
services.mysql.enable = true;
};
pkgs = import nixpkgs { system = "x86_64-linux"; };
in
pkgs.writeText "test" (pkgs.lib.evalModules {
modules = all-modules ++ [ custom-module ];
}).config.services.mysql.dataDir;
in {
inherit flakes dockerImages containerTest;
}; };
} }

View file

@ -1,2 +0,0 @@
*.hcl
*.html

View file

@ -0,0 +1,31 @@
job "plugin-nfs-controller" {
datacenters = [ "homelab-1" ]
group "controller" {
task "plugin" {
driver = "docker"
config {
image = "mcr.microsoft.com/k8s/csi/nfs-csi:latest" # "csi-driver-nfs:local"
args = [
"--endpoint=unix://csi/csi.sock",
"--nodeid=contoller",
"--logtostderr",
"-v=5",
]
}
csi_plugin {
id = "nfs"
type = "controller"
mount_dir = "/csi"
}
resources {
cpu = 250
memory = 128
}
}
}
}

View file

@ -1,54 +0,0 @@
#+PROPERTY: tangle "controller.nomad"
TODO The image that's currently being used is the "official" =nfs-csi-driver= image, while it works
it isn't very declarative, I should test the Nix based one.
#+NAME: docker-image
#+BEGIN_SRC hcl
image = "mcr.microsoft.com/k8s/csi/nfs-csi:latest" # "csi-driver-nfs:local"
#+END_SRC
The arguments passed to the =nfs-csi-driver= binary are actually quite interesting. First we
specify the endpoint, the socket is placed in =/csi= and =/csi= is actually a bind mounted directory,
which belongs to nomad as specified in the =csi_plugin= stanza. Nomad then connects to the socket.
All the arguments are standard and seem to be the same for almost all CSI plugins, I don't think
cmd line arguments are covered by the CSI specification though..
#+NAME: docker-args
#+BEGIN_SRC hcl
args = [
"--endpoint=unix://csi/csi.sock",
"--nodeid=contoller",
"--logtostderr",
"-v=5",
]
#+END_SRC
#+BEGIN_SRC hcl :noweb yes :tangle yes
job "plugin-nfs-controller" {
datacenters = [ "homelab-1" ]
group "controller" {
task "plugin" {
driver = "docker"
config {
<<docker-image>>
<<docker-args>>
}
csi_plugin {
id = "nfs"
type = "controller"
mount_dir = "/csi"
}
resources {
cpu = 250
memory = 128
}
}
}
}
#+END_SRC

View file

@ -0,0 +1,35 @@
job "plugin-nfs-nodes" {
datacenters = [ "homelab-1" ]
type = "system"
group "nodes" {
task "plugin" {
driver = "docker"
config {
image = "mcr.microsoft.com/k8s/csi/nfs-csi:latest" # "csi-driver-nfs:local"
args = [
"--endpoint=unix://csi/csi.sock",
"--nodeid=blowhole-0",
"--logtostderr",
"--v=5",
]
privileged = true
}
csi_plugin {
id = "nfs"
type = "node"
mount_dir = "/csi"
}
resources {
cpu = 250
memory = 128
}
}
}
}

View file

@ -1,65 +0,0 @@
#+PROPERTY: tangle "nodes.nomad"
For comments please see [[./nfs-controller.org][nfs-controller.org]], the org files are essentially the same, save for two difference. One being the
node ID, in this case it's necessary for them to be unique, which may be achieved with =consul-template=.
#+OPTIONS: toc:nil
#+TITLE: csi-nfs-driver Node Configuration
#+NAME: docker-args
#+BEGIN_SRC hcl
args = [
"--endpoint=unix://csi/csi.sock",
"--nodeid=blowhole-0",
"--logtostderr",
"--v=5",
]
#+END_SRC
Another difference is that we must explicitly set, what IP address wil the nodes get, this is not necessary if you don't
run your NFS server on the same machine as on of these nodes may run. However if this is the case, you must specify what
IP they'll get (or at the one sharing space with the NFS server). The NFS server will see the nodes internal IP, because
NAT isn't performed until the packet from the node, leave the host. That means that it's impossible to statically
configure your NFS server to properly identify that node, unless you enable Kerberos and whatnot. Note that this
requires that a static docker network be create on each machine you add into the Nomad cluster.
#+NAME: docker-ip
#+BEGIN_SRC hcl
network_mode = "nfs"
ipv4_address = "172.69.0.10"
#+END_SRC
Also, privileged is required here, because the nodes must be able to perform mounts.
#+BEGIN_SRC hcl :tangle yes :noweb yes
job "plugin-nfs-nodes" {
datacenters = [ "homelab-1" ]
type = "system"
group "nodes" {
task "plugin" {
driver = "docker"
config {
image = "mcr.microsoft.com/k8s/csi/nfs-csi:latest" # "csi-driver-nfs:local"
<<docker-args>>
privileged = true
}
csi_plugin {
id = "nfs"
type = "node"
mount_dir = "/csi"
}
resources {
cpu = 250
memory = 128
}
}
}
}
#+END_SRC

33
lib.nix
View file

@ -1,33 +0,0 @@
{ nixpkgs, pkgs, system, inputs }:
with pkgs.lib; {
substitute = runCommand: name: inFile: vars:
runCommand name {}
(let
varsStr = pkgs.lib.mapAttrsToList
(name: value: ''--subst-var-by "${name}" "${value}"'')
vars;
in
''
substitute ${inFile} $out \
${builtins.concatStringsSep " " varsStr}
'');
flakes = path: modules: genAttrs modules (module:
let
self = (import (path + "/${module}/flake.nix")).outputs (inputs // { inherit self; });
in
self
);
dockerImages = pkgs: path: modules: genAttrs modules (module:
import (path + "/${module}") ({ inherit pkgs system; } // inputs)
);
pkgsWithFlakes = flakes: import nixpkgs
{
inherit system;
overlays = builtins.concatLists (mapAttrsToList (_: flake:
if builtins.hasAttr "overlay" flake then
[ flake.overlay ]
else
[]
) flakes);
};
}

View file

@ -1,42 +0,0 @@
{
"nodes": {
"klippy": {
"flake": false,
"locked": {
"lastModified": 1609168797,
"narHash": "sha256-1ojKClZTqa0amwUWz1z9GFuEaXtuw7xu0JEgF2N1UQ8=",
"owner": "KevinOConnor",
"repo": "klipper",
"rev": "e68cf08d15a985ecce7497b58408ee233dd54eb9",
"type": "github"
},
"original": {
"owner": "KevinOConnor",
"repo": "klipper",
"rev": "e68cf08d15a985ecce7497b58408ee233dd54eb9",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1609867866,
"narHash": "sha256-ITciATW51g/VqL4CTCh74Cu/wqIztkoJNZJxqj2vEMs=",
"path": "/nix/store/gz0m2hylws210m0nr3ih8b8pvnikwi6f-source",
"rev": "4a75ca4a4e7d14e7b0b0230b3ea57b5bd7c16218",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"klippy": "klippy",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,119 +0,0 @@
{
inputs = {
nixpkgs.url = "nixpkgs";
klippy = {
url = "github:KevinOConnor/klipper?rev=e68cf08d15a985ecce7497b58408ee233dd54eb9";
flake = false;
};
};
outputs = { self, nixpkgs, ... }@inputs:
let
supportedSystems = [ "x86_64-linux" "i686-linux" "aarch64-linux" ];
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
in
{
overlay = final: prev:
with final; {
klippy = let
pythonPackages = python-packages: with python-packages; [
greenlet
cffi
pyserial
jinja2
];
pythonWithPackages = (python2.withPackages pythonPackages);
in stdenv.mkDerivation
{
name = "klippy";
src = inputs.klippy;
buildInputs = with pkgs; [ makeWrapper ];
dontBuild = true;
installPhase = ''
mkdir -p $out/share/klippy
cp -r klippy/* $out/share/klippy
mkdir -p $out/bin
chmod +x $out/share/klippy/klippy.py
makeWrapper \
$out/share/klippy/klippy.py \
$out/bin/klippy \
--prefix PATH : ${lib.makeBinPath (with pkgs; [
pythonWithPackages
])}
${pythonWithPackages}/bin/python $out/share/klippy/chelper/__init__.py
'';
};
};
defaultPackage = forAllSystems (system: (import nixpkgs {
inherit system;
overlays = [ self.overlay ];
}).klippy);
nixosModules.klippy = { pkgs, config, ... }: with nixpkgs.lib;
let
cfg = config.services.klippy;
in {
options.services.klippy = import ./options.nix { inherit pkgs config; };
config =
{
nixpkgs.overlays = [ self.overlay ];
users.users."${cfg.user}" = {
uid = cfg.uid;
description = "klippy user";
group = "${cfg.group}";
extraGroups = cfg.extraGroups;
};
users.groups."${cfg.group}" = {
gid = cfg.gid;
};
systemd.services = mapAttrs'
(name: value:
let
configFile = pkgs.writeText "printer.cfg" ''
${builtins.readFile value.config.file}
${foldl (str: acc: acc + str) "" (map (x: "[include " + x + "]\n") value.config.extraImports)}
${if value.config.virtualSd != "" then "[virtual_sdcard]\npath: " + value.config.virtualSd else ""}
'';
in
(nameValuePair
("klippy-" + name)
{
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
description = "Starts klipper-" + name;
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
RemainAfterExit = "yes";
ExecStart = ''
${value.package}/bin/klippy \
--input-tty ${value.inputTty} \
${if value.apiServer != "" then "--api-server " + value.apiServer else ""} \
${if value.logFile != "" then "--logfile " + value.logFile else ""} \
${if value.verbose then "-v" else ""} \
${if value.dictionary != "" then "--dictionary " + value.dictionary else ""} \
${configFile}
'';
ExecStartPost = "${pkgs.bash}/bin/bash -c '(sleep 5 ; [[ -e \"${value.apiServer}\" ]] && chmod 664 \"${value.apiServer}\" ) & disown'";
Restart = "always";
RestartSec = 10;
};
}))
cfg.instances;
};
};
};
}

View file

@ -1,134 +0,0 @@
{ pkgs, ... }: with pkgs.lib;
{
instances = mkOption {
description = "Klippy instances";
default = {};
example = {
package = pkgs.klippy;
inputTty = "/tmp/printer";
logFile = "/var/log/klippy.log";
};
type = types.attrsOf (types.submodule {
options = {
package = mkOption {
default = pkgs.klippy;
type = types.package;
description = ''
klippy package
'';
};
inputTty = mkOption {
default = "/tmp/printer";
type = types.str;
description = ''
inputs tty name
'';
};
apiServer = mkOption {
default = "/tmp/klippy_uds";
type = types.str;
description = ''
api server unix domain socket filename
'';
};
logFile = mkOption {
default = "";
type = types.str;
description = ''
write log to file instead of stderr
'';
};
verbose = mkOption {
default = false;
type = types.bool;
description = ''
enable debug messages
'';
};
dictionary = mkOption {
default = "";
type = types.str;
description = ''
file to read for mcu protocol dictionary
'';
};
config = mkOption {
default = {};
type = types.submodule {
options = {
file = mkOption {
default = "";
type = types.path;
description = ''
klipper config file
'';
};
extraImports = mkOption {
default = [];
type = types.listOf types.path;
description = ''
extra imports added at the end of the config
'';
};
virtualSd = mkOption {
default = "";
type = types.path;
description = ''
virtual sd folder
'';
};
};
};
};
};
});
};
user = mkOption {
default = "klippy";
type = types.str;
description = ''
the user for klippy
'';
};
uid = mkOption {
default = 5687;
type = types.int;
description = ''
the uid for the user for klippy
'';
};
group = mkOption {
default = "klippy";
type = types.str;
description = ''
the group for klippy
'';
};
gid = mkOption {
default = 5687;
type = types.int;
description = ''
the gid for the group for klippy
'';
};
extraGroups = mkOption {
default = [ "dialout" ];
type = types.listOf types.str;
description = ''
extra groups for klippy
'';
};
}

View file

@ -1,24 +0,0 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1609867866,
"narHash": "sha256-ITciATW51g/VqL4CTCh74Cu/wqIztkoJNZJxqj2vEMs=",
"path": "/nix/store/gz0m2hylws210m0nr3ih8b8pvnikwi6f-source",
"rev": "4a75ca4a4e7d14e7b0b0230b3ea57b5bd7c16218",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,127 +0,0 @@
{
inputs = {
nixpkgs.url = "nixpkgs";
};
outputs = { self, nixpkgs, ... }@inputs:
let
supportedSystems = [ "x86_64-linux" "i686-linux" "aarch64-linux" ];
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
in {
nixosModules.mainsail = { pkgs, config, ... }: with nixpkgs.lib;
let
cfg = config.services.mainsail;
in {
options.services.mainsail = {
enable = mkOption {
description = "Enable Mainsail NOTE: enable nginx too";
default = false;
type = types.bool;
};
apiServer = mkOption {
description = "IP and port of the moonraker apiserver";
default = "localhost:7125";
type = types.str;
};
printerCam = mkOption {
description = "IP and port of the webcam server";
default = "";
type = types.str;
};
virtualHost = mkOption {
description = "The virtual host for mainsail in nginx";
default = "mainsail.localhost";
type = types.str;
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = mkForce true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
clientMaxBodySize = "200M";
# commonHttpConfig = ''
# map $http_upgrade $connection_upgrade {
# default upgrade;
# \'\' close;
# }
# '';
virtualHosts."${cfg.virtualHost}" = {
root = pkgs.fetchzip {
url = "https://github.com/meteyou/mainsail/releases/download/v0.4.0/mainsail.zip";
sha256 = "PBu3ktVCchi+E54cuKzsRhZXWkWG/NvOf+IZNSNN8fw=";
stripRoot = false;
};
locations = let
apiServer = cfg.apiServer;
printerCam = cfg.printerCam;
extraConfig = ''
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Scheme $scheme;
'';
in {
"/" = {
extraConfig = ''
try_files $uri $uri/ /index.html;
'';
};
"/printer" = {
proxyPass = "http://${apiServer}/printer";
inherit extraConfig;
};
"/api" = {
proxyPass = "http://${apiServer}/api";
inherit extraConfig;
};
"/access" = {
proxyPass = "http://${apiServer}/access";
inherit extraConfig;
};
"/websocket" = {
proxyPass = "http://${apiServer}/websocket";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400;
'';
};
"/machine" = {
proxyPass = "http://${apiServer}/machine";
inherit extraConfig;
};
"/server" = {
proxyPass = "http://${apiServer}/server";
inherit extraConfig;
};
"/webcam/" = mkIf (printerCam != "") {
proxyPass = "http://${printerCam}/";
};
};
};
};
};
};
};
}

View file

@ -1,31 +0,0 @@
r
"nodes": {
"moonraker": {
"flake": false,
"locked": {
"lastModified": 1609164221,
"narHash": "sha256-+k4bFTGWvJ+un8R9dRhjtDt4dVvHfu2/gSp5iEuoX/w=",
"owner": "MagicRB",
"repo": "moonraker",
"rev": "e63f104695278231c3961b12bc5f5e13f5eeea62",
"type": "github"
},
"original": {
"owner": "MagicRB",
"ref": "master",
"repo": "moonraker",
"type": "github"
}
},
"root": {
"inputs": {
"moonraker": "moonraker",
"nixpkgs": [
"nixpkgs"
]
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,18 +0,0 @@
value: lib: with lib;
''
[server]
host: ${value.config.server.host}
port: ${builtins.toString value.config.server.port}
klippy_uds_address: ${value.config.server.klippyUdsAddress}
max_upload_size: ${builtins.toString value.config.server.maxUploadSize}
enable_debug_logging: ${if value.config.server.enableDebugLogging then "True" else "False"}
${if value.config.server.configPath != "" then "config_path: " + value.config.authorization.configPath else ""}
[authorization]
enabled: ${if value.config.authorization.enabled then "True" else "False"}
${if value.config.authorization.apiKeyFile != "" then "api_key_file: " + value.config.authorization.apiKeyFile else ""}
trusted_clients:
${foldl (str: acc: acc + str) "" (map (x: " " + x + "\n") value.config.authorization.trustedClients)}
cors_domains:
${foldl (str: acc: acc + str) "" (map (x: " " + x + "\n") value.config.authorization.corsDomains)}
''

View file

@ -1,42 +0,0 @@
{
"nodes": {
"moonraker": {
"flake": false,
"locked": {
"lastModified": 1609164221,
"narHash": "sha256-+k4bFTGWvJ+un8R9dRhjtDt4dVvHfu2/gSp5iEuoX/w=",
"owner": "MagicRB",
"repo": "moonraker",
"rev": "e63f104695278231c3961b12bc5f5e13f5eeea62",
"type": "github"
},
"original": {
"owner": "MagicRB",
"ref": "master",
"repo": "moonraker",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1609867866,
"narHash": "sha256-ITciATW51g/VqL4CTCh74Cu/wqIztkoJNZJxqj2vEMs=",
"path": "/nix/store/gz0m2hylws210m0nr3ih8b8pvnikwi6f-source",
"rev": "4a75ca4a4e7d14e7b0b0230b3ea57b5bd7c16218",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"moonraker": "moonraker",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,106 +0,0 @@
{
inputs = {
nixpkgs.url = "nixpkgs";
moonraker = {
url = "github:MagicRB/moonraker?ref=master";
flake = false;
};
};
outputs = { self, nixpkgs, ... }@inputs:
let
supportedSystems = [ "x86_64-linux" "i686-linux" "aarch64-linux" ];
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
in
{
overlay = final: prev:
with final; {
moonraker = let
pythonPackages = python-packages: with python-packages; [
tornado
pyserial
pillow
];
pythonWithPackages = (python3.withPackages pythonPackages);
in stdenv.mkDerivation
{
name = "moonraker";
src = inputs.moonraker;
buildInputs = with pkgs; [ makeWrapper ];
dontBuild = true;
installPhase = ''
mkdir -p $out/share/moonraker
cp -r * $out/share/moonraker
mkdir -p out/bin
chmod +x $out/share/moonraker/moonraker/moonraker.py
makeWrapper \
$out/share/moonraker/moonraker/moonraker.py \
$out/bin/moonraker \
--prefix PATH : ${lib.makeBinPath (with pkgs; [
pythonWithPackages
])}
'';
};
};
nixosModules.moonraker = { pkgs, config, ... }: with nixpkgs.lib;
let
cfg = config.services.moonraker;
in {
options.services.moonraker = import ./options.nix { inherit pkgs config; };
config =
{
nixpkgs.overlays = [ self.overlay ];
users.users."${cfg.user}" = mkIf cfg.createUser {
uid = cfg.uid;
description = "klippy user";
group = "${cfg.group}";
extraGroups = cfg.extraGroups;
};
users.groups."${cfg.group}" = mkIf cfg.createGroup {
gid = cfg.gid;
};
systemd.services = mapAttrs'
(name: value:
let
configFile = pkgs.writeText "moonraker.conf" (import ./config.nix value pkgs.lib);
in (nameValuePair
("moonraker-" + name)
{
wantedBy = [ "muti-user.target" ];
after = [ "network.target" ];
description = "Starts moonraker-" + name;
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
RemainAfterExit = "yes";
ExecStart = ''
${value.package}/bin/moonraker \
--configfile ${configFile} \
--logfile ${value.logFile}
'';
Restart = "always";
RestartSec = 10;
};
}))
cfg.instances;
};
};
defaultPackage = forAllSystems (system: (import nixpkgs {
inherit system;
overlays = [ self.overlay ];
}).moonraker);
};
}

View file

@ -1,183 +0,0 @@
{ pkgs, ... }: with pkgs.lib; {
instances = mkOption {
default = {};
description = "Moonraker instances";
type = types.attrsOf (types.submodule {
options = {
package = mkOption {
default = pkgs.moonraker;
type = types.package;
description = ''
moonraker package
'';
};
config = mkOption {
default = {};
type = types.submodule {
options = {
server = mkOption {
default = {};
type = types.submodule {
options = {
host = mkOption {
default = "0.0.0.0";
type = types.str;
description = ''
The host address in which to bind the HTTP server.
'';
};
port = mkOption {
default = 7125;
type = types.int;
description = ''
The port the HTTP server will listen on.
'';
};
klippyUdsAddress = mkOption {
default = "/tmp/klippy_uds";
type = types.str;
description = ''
The address of Unix Domain Socket used to communicate with Klippy.
'';
};
maxUploadSize = mkOption {
default = 200;
type = types.int;
description = ''
The maximum size allowed for a file upload. Default is 200 MiB.
'';
};
enableDebugLogging = mkOption {
default = true;
type = types.bool;
description = ''
When set to True Moonraker will log in verbose mode.
'';
};
configPath = mkOption {
default = "";
type = types.str;
description = ''
The path to a directory where configuration files are located.
'';
};
};
};
};
authorization = mkOption {
default = {};
type = types.submodule {
options = {
enabled = mkOption {
default = true;
type = types.bool;
description = ''
Enables authorization.
'';
};
apiKeyFile = mkOption {
default = "/tmp/.moonraker_api_key";
type = types.str;
description = ''
Path of the file that stores Moonraker's API key.
'';
};
trustedClients = mkOption {
default = [];
type = types.listOf types.str;
description = ''
A list of newline separated ip addresses and/or ip ranges that are trusted.
'';
};
corsDomains = mkOption {
default = [];
type = types.listOf types.str;
description = ''
Enables CORS for the specified domains.
'';
};
};
};
};
};
};
};
logFile = mkOption {
default = "/tmp/moonraker.log";
type = types.str;
description = ''
moonraker log file
'';
};
};
});
};
user = mkOption {
default = "moonraker";
type = types.str;
description = ''
moonraker user
'';
};
uid = mkOption {
default = 5688;
type = types.int;
description = ''
moonraker user id
'';
};
group = mkOption {
default = "moonraker";
type = types.str;
description = ''
moonraker group
'';
};
gid = mkOption {
default = 5688;
type = types.int;
description = ''
moonraker group id
'';
};
extraGroups = mkOption {
default = [ "klippy" ];
type = types.listOf types.str;
description = ''
extra groups for moonraker user
'';
};
createUser = mkOption {
default = true;
type = types.bool;
description = ''
create user
'';
};
createGroup = mkOption {
default = true;
type = types.bool;
description = ''
create group
'';
};
}