Merge branch 'staging-next' into staging
This commit is contained in:
commit
306cc9b311
|
@ -20,4 +20,5 @@
|
||||||
<xi:include href="functions/appimagetools.xml" />
|
<xi:include href="functions/appimagetools.xml" />
|
||||||
<xi:include href="functions/prefer-remote-fetch.xml" />
|
<xi:include href="functions/prefer-remote-fetch.xml" />
|
||||||
<xi:include href="functions/nix-gitignore.xml" />
|
<xi:include href="functions/nix-gitignore.xml" />
|
||||||
|
<xi:include href="functions/ocitools.xml" />
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
<section xmlns="http://docbook.org/ns/docbook"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||||
|
xml:id="sec-pkgs-ociTools">
|
||||||
|
<title>pkgs.ociTools</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<varname>pkgs.ociTools</varname> is a set of functions for creating
|
||||||
|
containers according to the
|
||||||
|
<link xlink:href="https://github.com/opencontainers/runtime-spec">OCI
|
||||||
|
container specification v1.0.0</link>. Beyond that it makes no assumptions
|
||||||
|
about the container runner you choose to use to run the created container.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section xml:id="ssec-pkgs-ociTools-buildContainer">
|
||||||
|
<title>buildContainer</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This function creates a simple OCI container that runs a single command
|
||||||
|
inside of it. An OCI container consists of a <varname>config.json</varname>
|
||||||
|
and a rootfs directory.The nix store of the container will contain all
|
||||||
|
referenced dependencies of the given command.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The parameters of <varname>buildContainer</varname> with an example value
|
||||||
|
are described below:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<example xml:id='ex-ociTools-buildContainer'>
|
||||||
|
<title>Build Container</title>
|
||||||
|
<programlisting>
|
||||||
|
buildContainer {
|
||||||
|
cmd = with pkgs; writeScript "run.sh" ''
|
||||||
|
#!${bash}/bin/bash
|
||||||
|
${coreutils}/bin/exec ${bash}/bin/bash
|
||||||
|
''; <co xml:id='ex-ociTools-buildContainer-1' />
|
||||||
|
|
||||||
|
mounts = {
|
||||||
|
"/data" = {
|
||||||
|
type = "none";
|
||||||
|
source = "/var/lib/mydata";
|
||||||
|
options = [ "bind" ];
|
||||||
|
};
|
||||||
|
};<co xml:id='ex-ociTools-buildContainer-2' />
|
||||||
|
|
||||||
|
readonly = false; <co xml:id='ex-ociTools-buildContainer-3' />
|
||||||
|
}
|
||||||
|
|
||||||
|
</programlisting>
|
||||||
|
<calloutlist>
|
||||||
|
<callout arearefs='ex-ociTools-buildContainer-1'>
|
||||||
|
<para>
|
||||||
|
<varname>cmd</varname> specifies the program to run inside the container.
|
||||||
|
This is the only required argument for <varname>buildContainer</varname>.
|
||||||
|
All referenced packages inside the derivation will be made available
|
||||||
|
inside the container
|
||||||
|
</para>
|
||||||
|
</callout>
|
||||||
|
<callout arearefs='ex-ociTools-buildContainer-2'>
|
||||||
|
<para>
|
||||||
|
<varname>mounts</varname> specifies additional mount points chosen by the
|
||||||
|
user. By default only a minimal set of necessary filesystems are mounted
|
||||||
|
into the container (e.g procfs, cgroupfs)
|
||||||
|
</para>
|
||||||
|
</callout>
|
||||||
|
<callout arearefs='ex-ociTools-buildContainer-3'>
|
||||||
|
<para>
|
||||||
|
<varname>readonly</varname> makes the container's rootfs read-only if it is set to true.
|
||||||
|
The default value is false <literal>false</literal>.
|
||||||
|
</para>
|
||||||
|
</callout>
|
||||||
|
</calloutlist>
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
</section>
|
|
@ -2714,6 +2714,49 @@ nativeBuildInputs = [ breakpointHook ];
|
||||||
</note>
|
</note>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
installShellFiles
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This hook helps with installing manpages and shell completion files. It
|
||||||
|
exposes 2 shell functions <literal>installManPage</literal> and
|
||||||
|
<literal>installShellCompletion</literal> that can be used from your
|
||||||
|
<literal>postInstall</literal> hook.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>installManPage</literal> function takes one or more paths
|
||||||
|
to manpages to install. The manpages must have a section suffix, and may
|
||||||
|
optionally be compressed (with <literal>.gz</literal> suffix). This
|
||||||
|
function will place them into the correct directory.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>installShellCompletion</literal> function takes one or more
|
||||||
|
paths to shell completion files. By default it will autodetect the shell
|
||||||
|
type from the completion file extension, but you may also specify it by
|
||||||
|
passing one of <literal>--bash</literal>, <literal>--fish</literal>, or
|
||||||
|
<literal>--zsh</literal>. These flags apply to all paths listed after
|
||||||
|
them (up until another shell flag is given). Each path may also have a
|
||||||
|
custom installation name provided by providing a flag <literal>--name
|
||||||
|
NAME</literal> before the path. If this flag is not provided, zsh
|
||||||
|
completions will be renamed automatically such that
|
||||||
|
<literal>foobar.zsh</literal> becomes <literal>_foobar</literal>.
|
||||||
|
<programlisting>
|
||||||
|
nativeBuildInputs = [ installShellFiles ];
|
||||||
|
postInstall = ''
|
||||||
|
installManPage doc/foobar.1 doc/barfoo.3
|
||||||
|
# explicit behavior
|
||||||
|
installShellCompletion --bash --name foobar.bash share/completions.bash
|
||||||
|
installShellCompletion --fish --name foobar.fish share/completions.fish
|
||||||
|
installShellCompletion --zsh --name _foobar share/completions.zsh
|
||||||
|
# implicit behavior
|
||||||
|
installShellCompletion share/completions/foobar.{bash,fish,zsh}
|
||||||
|
'';
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
libiconv, libintl
|
libiconv, libintl
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
<para>
|
<para>
|
||||||
Apart from high-level options, it’s possible to tweak a package in almost
|
Apart from high-level options, it’s possible to tweak a package in almost
|
||||||
arbitrary ways, such as changing or disabling dependencies of a package. For
|
arbitrary ways, such as changing or disabling dependencies of a package. For
|
||||||
instance, the Emacs package in Nixpkgs by default has a dependency on GTK+ 2.
|
instance, the Emacs package in Nixpkgs by default has a dependency on GTK 2.
|
||||||
If you want to build it against GTK+ 3, you can specify that as follows:
|
If you want to build it against GTK 3, you can specify that as follows:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<xref linkend="opt-environment.systemPackages"/> = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];
|
<xref linkend="opt-environment.systemPackages"/> = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
function that produces Emacs, with the original arguments amended by the set
|
function that produces Emacs, with the original arguments amended by the set
|
||||||
of arguments specified by you. So here the function argument
|
of arguments specified by you. So here the function argument
|
||||||
<varname>gtk</varname> gets the value <literal>pkgs.gtk3</literal>, causing
|
<varname>gtk</varname> gets the value <literal>pkgs.gtk3</literal>, causing
|
||||||
Emacs to depend on GTK+ 3. (The parentheses are necessary because in Nix,
|
Emacs to depend on GTK 3. (The parentheses are necessary because in Nix,
|
||||||
function application binds more weakly than list construction, so without
|
function application binds more weakly than list construction, so without
|
||||||
them, <xref linkend="opt-environment.systemPackages"/> would be a list with
|
them, <xref linkend="opt-environment.systemPackages"/> would be a list with
|
||||||
two elements.)
|
two elements.)
|
||||||
|
|
|
@ -730,7 +730,7 @@ in
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<literal>jre</literal> now defaults to GTK+ UI by default. This improves
|
<literal>jre</literal> now defaults to GTK UI by default. This improves
|
||||||
visual consistency and makes Java follow system font style, improving the
|
visual consistency and makes Java follow system font style, improving the
|
||||||
situation on HighDPI displays. This has a cost of increased closure size;
|
situation on HighDPI displays. This has a cost of increased closure size;
|
||||||
for server and other headless workloads it's recommended to use
|
for server and other headless workloads it's recommended to use
|
||||||
|
|
|
@ -422,6 +422,12 @@
|
||||||
It was not useful except for debugging purposes and was confusingly set as default in some circumstances.
|
It was not useful except for debugging purposes and was confusingly set as default in some circumstances.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The WeeChat plugin <literal>pkgs.weechatScripts.weechat-xmpp</literal> has been removed as it doesn't receive
|
||||||
|
any updates from upstream and depends on outdated Python2-based modules.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
@ -710,6 +716,22 @@
|
||||||
<literal>nix-shell -p altcoins.dogecoin</literal>, etc.
|
<literal>nix-shell -p altcoins.dogecoin</literal>, etc.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Ceph has been upgraded to v14.2.1.
|
||||||
|
See the <link xlink:href="https://ceph.com/releases/v14-2-0-nautilus-released/">release notes</link> for details.
|
||||||
|
The mgr dashboard as well as osds backed by loop-devices is no longer explicitly supported by the package and module.
|
||||||
|
Note: There's been some issues with python-cherrypy, which is used by the dashboard
|
||||||
|
and prometheus mgr modules (and possibly others), hence 0000-dont-check-cherrypy-version.patch.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>pkgs.weechat</literal> is now compiled against <literal>pkgs.python3</literal>.
|
||||||
|
Weechat also recommends <link xlink:href="https://weechat.org/scripts/python3/">to use Python3
|
||||||
|
in their docs.</link>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -17,7 +17,7 @@ in {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = "The name of the generated derivation";
|
description = "The name of the generated derivation";
|
||||||
default = "nixos-disk-image";
|
default = "nixos-amazon-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}";
|
||||||
};
|
};
|
||||||
|
|
||||||
contents = mkOption {
|
contents = mkOption {
|
||||||
|
@ -42,7 +42,7 @@ in {
|
||||||
|
|
||||||
format = mkOption {
|
format = mkOption {
|
||||||
type = types.enum [ "raw" "qcow2" "vpc" ];
|
type = types.enum [ "raw" "qcow2" "vpc" ];
|
||||||
default = "qcow2";
|
default = "vpc";
|
||||||
description = "The image format to output";
|
description = "The image format to output";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -51,7 +51,9 @@ in {
|
||||||
inherit lib config;
|
inherit lib config;
|
||||||
inherit (cfg) contents format name;
|
inherit (cfg) contents format name;
|
||||||
pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
|
pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
|
||||||
partitionTableType = if config.ec2.hvm then "legacy" else "none";
|
partitionTableType = if config.ec2.efi then "efi"
|
||||||
|
else if config.ec2.hvm then "legacy"
|
||||||
|
else "none";
|
||||||
diskSize = cfg.sizeMB;
|
diskSize = cfg.sizeMB;
|
||||||
fsType = "ext4";
|
fsType = "ext4";
|
||||||
configFile = pkgs.writeText "configuration.nix"
|
configFile = pkgs.writeText "configuration.nix"
|
||||||
|
@ -61,7 +63,27 @@ in {
|
||||||
${optionalString config.ec2.hvm ''
|
${optionalString config.ec2.hvm ''
|
||||||
ec2.hvm = true;
|
ec2.hvm = true;
|
||||||
''}
|
''}
|
||||||
|
${optionalString config.ec2.efi ''
|
||||||
|
ec2.efi = true;
|
||||||
|
''}
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
postVM = ''
|
||||||
|
extension=''${diskImage##*.}
|
||||||
|
friendlyName=$out/${cfg.name}.$extension
|
||||||
|
mv "$diskImage" "$friendlyName"
|
||||||
|
diskImage=$friendlyName
|
||||||
|
|
||||||
|
mkdir -p $out/nix-support
|
||||||
|
echo "file ${cfg.format} $diskImage" >> $out/nix-support/hydra-build-products
|
||||||
|
|
||||||
|
${pkgs.jq}/bin/jq -n \
|
||||||
|
--arg label ${lib.escapeShellArg config.system.nixos.label} \
|
||||||
|
--arg system ${lib.escapeShellArg pkgs.stdenv.hostPlatform.system} \
|
||||||
|
--arg logical_bytes "$(${pkgs.qemu}/bin/qemu-img info --output json "$diskImage" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||||
|
--arg file "$diskImage" \
|
||||||
|
'$ARGS.named' \
|
||||||
|
> $out/nix-support/image-info.json
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,279 +1,296 @@
|
||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#! nix-shell -i bash -p qemu ec2_ami_tools jq ec2_api_tools awscli
|
#!nix-shell -p awscli -p jq -p qemu -i bash
|
||||||
|
|
||||||
# To start with do: nix-shell -p awscli --run "aws configure"
|
# Uploads and registers NixOS images built from the
|
||||||
|
# <nixos/release.nix> amazonImage attribute. Images are uploaded and
|
||||||
|
# registered via a home region, and then copied to other regions.
|
||||||
|
|
||||||
set -e
|
# The home region requires an s3 bucket, and a "vmimport" IAM role
|
||||||
set -o pipefail
|
# with access to the S3 bucket. Configuration of the vmimport role is
|
||||||
|
# documented in
|
||||||
|
# https://docs.aws.amazon.com/vm-import/latest/userguide/vmimport-image-import.html
|
||||||
|
|
||||||
version=$(nix-instantiate --eval --strict '<nixpkgs>' -A lib.version | sed s/'"'//g)
|
# set -x
|
||||||
major=${version:0:5}
|
set -euo pipefail
|
||||||
echo "NixOS version is $version ($major)"
|
|
||||||
|
|
||||||
stateDir=/home/deploy/amis/ec2-image-$version
|
|
||||||
echo "keeping state in $stateDir"
|
|
||||||
mkdir -p $stateDir
|
|
||||||
|
|
||||||
rm -f ec2-amis.nix
|
|
||||||
|
|
||||||
types="hvm"
|
|
||||||
stores="ebs"
|
|
||||||
regions="eu-west-1 eu-west-2 eu-west-3 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1"
|
|
||||||
|
|
||||||
for type in $types; do
|
|
||||||
link=$stateDir/$type
|
|
||||||
imageFile=$link/nixos.qcow2
|
|
||||||
system=x86_64-linux
|
|
||||||
arch=x86_64
|
|
||||||
|
|
||||||
# Build the image.
|
|
||||||
if ! [ -L $link ]; then
|
|
||||||
if [ $type = pv ]; then hvmFlag=false; else hvmFlag=true; fi
|
|
||||||
|
|
||||||
echo "building image type '$type'..."
|
|
||||||
nix-build -o $link \
|
|
||||||
'<nixpkgs/nixos>' \
|
|
||||||
-A config.system.build.amazonImage \
|
|
||||||
--arg configuration "{ imports = [ <nixpkgs/nixos/maintainers/scripts/ec2/amazon-image.nix> ]; ec2.hvm = $hvmFlag; }"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for store in $stores; do
|
|
||||||
|
|
||||||
|
# configuration
|
||||||
|
state_dir=/home/deploy/amis/ec2-images
|
||||||
|
home_region=eu-west-1
|
||||||
bucket=nixos-amis
|
bucket=nixos-amis
|
||||||
bucketDir="$version-$type-$store"
|
|
||||||
|
|
||||||
prevAmi=
|
regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1
|
||||||
prevRegion=
|
us-east-1 us-east-2 us-west-1 us-west-2
|
||||||
|
ca-central-1
|
||||||
|
ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2
|
||||||
|
ap-south-1 ap-east-1
|
||||||
|
sa-east-1)
|
||||||
|
|
||||||
for region in $regions; do
|
log() {
|
||||||
|
echo "$@" >&2
|
||||||
|
}
|
||||||
|
|
||||||
name=nixos-$version-$arch-$type-$store
|
if [ -z "$1" ]; then
|
||||||
description="NixOS $system $version ($type-$store)"
|
log "Usage: ./upload-amazon-image.sh IMAGE_OUTPUT"
|
||||||
|
exit 1
|
||||||
amiFile=$stateDir/$region.$type.$store.ami-id
|
|
||||||
|
|
||||||
if ! [ -e $amiFile ]; then
|
|
||||||
|
|
||||||
echo "doing $name in $region..."
|
|
||||||
|
|
||||||
if [ -n "$prevAmi" ]; then
|
|
||||||
ami=$(aws ec2 copy-image \
|
|
||||||
--region "$region" \
|
|
||||||
--source-region "$prevRegion" --source-image-id "$prevAmi" \
|
|
||||||
--name "$name" --description "$description" | jq -r '.ImageId')
|
|
||||||
if [ "$ami" = null ]; then break; fi
|
|
||||||
else
|
|
||||||
|
|
||||||
if [ $store = s3 ]; then
|
|
||||||
|
|
||||||
# Bundle the image.
|
|
||||||
imageDir=$stateDir/$type-bundled
|
|
||||||
|
|
||||||
# Convert the image to raw format.
|
|
||||||
rawFile=$stateDir/$type.raw
|
|
||||||
if ! [ -e $rawFile ]; then
|
|
||||||
qemu-img convert -f qcow2 -O raw $imageFile $rawFile.tmp
|
|
||||||
mv $rawFile.tmp $rawFile
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [ -d $imageDir ]; then
|
# result of the amazon-image from nixos/release.nix
|
||||||
rm -rf $imageDir.tmp
|
store_path=$1
|
||||||
mkdir -p $imageDir.tmp
|
|
||||||
ec2-bundle-image \
|
if [ ! -e "$store_path" ]; then
|
||||||
-d $imageDir.tmp \
|
log "Store path: $store_path does not exist, fetching..."
|
||||||
-i $rawFile --arch $arch \
|
nix-store --realise "$store_path"
|
||||||
--user "$AWS_ACCOUNT" -c "$EC2_CERT" -k "$EC2_PRIVATE_KEY"
|
|
||||||
mv $imageDir.tmp $imageDir
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Upload the bundle to S3.
|
if [ ! -d "$store_path" ]; then
|
||||||
if ! [ -e $imageDir/uploaded ]; then
|
log "store_path: $store_path is not a directory. aborting"
|
||||||
echo "uploading bundle to S3..."
|
exit 1
|
||||||
ec2-upload-bundle \
|
|
||||||
-m $imageDir/$type.raw.manifest.xml \
|
|
||||||
-b "$bucket/$bucketDir" \
|
|
||||||
-a "$AWS_ACCESS_KEY_ID" -s "$AWS_SECRET_ACCESS_KEY" \
|
|
||||||
--location EU
|
|
||||||
touch $imageDir/uploaded
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
extraFlags="--image-location $bucket/$bucketDir/$type.raw.manifest.xml"
|
read_image_info() {
|
||||||
|
if [ ! -e "$store_path/nix-support/image-info.json" ]; then
|
||||||
else
|
log "Image missing metadata"
|
||||||
|
exit 1
|
||||||
# Convert the image to vhd format so we don't have
|
|
||||||
# to upload a huge raw image.
|
|
||||||
vhdFile=$stateDir/$type.vhd
|
|
||||||
if ! [ -e $vhdFile ]; then
|
|
||||||
qemu-img convert -f qcow2 -O vpc $imageFile $vhdFile.tmp
|
|
||||||
mv $vhdFile.tmp $vhdFile
|
|
||||||
fi
|
fi
|
||||||
|
jq -r "$1" "$store_path/nix-support/image-info.json"
|
||||||
|
}
|
||||||
|
|
||||||
vhdFileLogicalBytes="$(qemu-img info "$vhdFile" | grep ^virtual\ size: | cut -f 2 -d \( | cut -f 1 -d \ )"
|
# We handle a single image per invocation, store all attributes in
|
||||||
vhdFileLogicalGigaBytes=$(((vhdFileLogicalBytes-1)/1024/1024/1024+1)) # Round to the next GB
|
# globals for convenience.
|
||||||
|
image_label=$(read_image_info .label)
|
||||||
|
image_system=$(read_image_info .system)
|
||||||
|
image_file=$(read_image_info .file)
|
||||||
|
image_logical_bytes=$(read_image_info .logical_bytes)
|
||||||
|
|
||||||
echo "Disk size is $vhdFileLogicalBytes bytes. Will be registered as $vhdFileLogicalGigaBytes GB."
|
# Derived attributes
|
||||||
|
|
||||||
taskId=$(cat $stateDir/$region.$type.task-id 2> /dev/null || true)
|
image_logical_gigabytes=$((($image_logical_bytes-1)/1024/1024/1024+1)) # Round to the next GB
|
||||||
volId=$(cat $stateDir/$region.$type.vol-id 2> /dev/null || true)
|
|
||||||
snapId=$(cat $stateDir/$region.$type.snap-id 2> /dev/null || true)
|
|
||||||
|
|
||||||
# Import the VHD file.
|
case "$image_system" in
|
||||||
if [ -z "$snapId" -a -z "$volId" -a -z "$taskId" ]; then
|
aarch64-linux)
|
||||||
echo "importing $vhdFile..."
|
amazon_arch=arm64
|
||||||
taskId=$(ec2-import-volume $vhdFile --no-upload -f vhd \
|
;;
|
||||||
-O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
|
x86_64-linux)
|
||||||
-o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY" \
|
amazon_arch=x86_64
|
||||||
--region "$region" -z "${region}a" \
|
;;
|
||||||
--bucket "$bucket" --prefix "$bucketDir/" \
|
*)
|
||||||
| tee /dev/stderr \
|
log "Unknown system: $image_system"
|
||||||
| sed 's/.*\(import-vol-[0-9a-z]\+\).*/\1/ ; t ; d')
|
exit 1
|
||||||
echo -n "$taskId" > $stateDir/$region.$type.task-id
|
esac
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$snapId" -a -z "$volId" ]; then
|
image_name="NixOS-${image_label}-${image_system}"
|
||||||
ec2-resume-import $vhdFile -t "$taskId" --region "$region" \
|
image_description="NixOS ${image_label} ${image_system}"
|
||||||
-O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
|
|
||||||
-o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wait for the volume creation to finish.
|
log "Image Details:"
|
||||||
if [ -z "$snapId" -a -z "$volId" ]; then
|
log " Name: $image_name"
|
||||||
echo "waiting for import to finish..."
|
log " Description: $image_description"
|
||||||
|
log " Size (gigabytes): $image_logical_gigabytes"
|
||||||
|
log " System: $image_system"
|
||||||
|
log " Amazon Arch: $amazon_arch"
|
||||||
|
|
||||||
|
read_state() {
|
||||||
|
local state_key=$1
|
||||||
|
local type=$2
|
||||||
|
|
||||||
|
cat "$state_dir/$state_key.$type" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
write_state() {
|
||||||
|
local state_key=$1
|
||||||
|
local type=$2
|
||||||
|
local val=$3
|
||||||
|
|
||||||
|
mkdir -p $state_dir
|
||||||
|
echo "$val" > "$state_dir/$state_key.$type"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_import() {
|
||||||
|
local region=$1
|
||||||
|
local task_id=$2
|
||||||
|
local state snapshot_id
|
||||||
|
log "Waiting for import task $task_id to be completed"
|
||||||
while true; do
|
while true; do
|
||||||
volId=$(aws ec2 describe-conversion-tasks --conversion-task-ids "$taskId" --region "$region" | jq -r .ConversionTasks[0].ImportVolume.Volume.Id)
|
read state progress snapshot_id < <(
|
||||||
if [ "$volId" != null ]; then break; fi
|
aws ec2 describe-import-snapshot-tasks --region $region --import-task-ids "$task_id" | \
|
||||||
|
jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail | "\(.Status) \(.Progress) \(.SnapshotId)"'
|
||||||
|
)
|
||||||
|
log " ... state=$state progress=$progress snapshot_id=$snapshot_id"
|
||||||
|
case "$state" in
|
||||||
|
active)
|
||||||
sleep 10
|
sleep 10
|
||||||
|
;;
|
||||||
|
completed)
|
||||||
|
echo "$snapshot_id"
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "Unexpected snapshot import state: '${state}'"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
|
}
|
||||||
|
|
||||||
echo -n "$volId" > $stateDir/$region.$type.vol-id
|
wait_for_image() {
|
||||||
fi
|
local region=$1
|
||||||
|
local ami_id=$2
|
||||||
|
local state
|
||||||
|
log "Waiting for image $ami_id to be available"
|
||||||
|
|
||||||
# Delete the import task.
|
|
||||||
if [ -n "$volId" -a -n "$taskId" ]; then
|
|
||||||
echo "removing import task..."
|
|
||||||
ec2-delete-disk-image -t "$taskId" --region "$region" \
|
|
||||||
-O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
|
|
||||||
-o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY" || true
|
|
||||||
rm -f $stateDir/$region.$type.task-id
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create a snapshot.
|
|
||||||
if [ -z "$snapId" ]; then
|
|
||||||
echo "creating snapshot..."
|
|
||||||
# FIXME: this can fail with InvalidVolume.NotFound. Eventual consistency yay.
|
|
||||||
snapId=$(aws ec2 create-snapshot --volume-id "$volId" --region "$region" --description "$description" | jq -r .SnapshotId)
|
|
||||||
if [ "$snapId" = null ]; then exit 1; fi
|
|
||||||
echo -n "$snapId" > $stateDir/$region.$type.snap-id
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wait for the snapshot to finish.
|
|
||||||
echo "waiting for snapshot to finish..."
|
|
||||||
while true; do
|
while true; do
|
||||||
status=$(aws ec2 describe-snapshots --snapshot-ids "$snapId" --region "$region" | jq -r .Snapshots[0].State)
|
read state < <(
|
||||||
if [ "$status" = completed ]; then break; fi
|
aws ec2 describe-images --image-ids "$ami_id" --region $region | \
|
||||||
|
jq -r ".Images[].State"
|
||||||
|
)
|
||||||
|
log " ... state=$state"
|
||||||
|
case "$state" in
|
||||||
|
pending)
|
||||||
sleep 10
|
sleep 10
|
||||||
|
;;
|
||||||
|
available)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "Unexpected AMI state: '${state}'"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# Delete the volume.
|
|
||||||
if [ -n "$volId" ]; then
|
|
||||||
echo "deleting volume..."
|
|
||||||
aws ec2 delete-volume --volume-id "$volId" --region "$region" || true
|
|
||||||
rm -f $stateDir/$region.$type.vol-id
|
|
||||||
fi
|
|
||||||
|
|
||||||
blockDeviceMappings="DeviceName=/dev/sda1,Ebs={SnapshotId=$snapId,VolumeSize=$vhdFileLogicalGigaBytes,DeleteOnTermination=true,VolumeType=gp2}"
|
make_image_public() {
|
||||||
extraFlags=""
|
local region=$1
|
||||||
|
local ami_id=$2
|
||||||
|
|
||||||
if [ $type = pv ]; then
|
wait_for_image $region "$ami_id"
|
||||||
extraFlags+=" --root-device-name /dev/sda1"
|
|
||||||
else
|
|
||||||
extraFlags+=" --root-device-name /dev/sda1"
|
|
||||||
extraFlags+=" --sriov-net-support simple"
|
|
||||||
extraFlags+=" --ena-support"
|
|
||||||
fi
|
|
||||||
|
|
||||||
blockDeviceMappings+=" DeviceName=/dev/sdb,VirtualName=ephemeral0"
|
log "Making image $ami_id public"
|
||||||
blockDeviceMappings+=" DeviceName=/dev/sdc,VirtualName=ephemeral1"
|
|
||||||
blockDeviceMappings+=" DeviceName=/dev/sdd,VirtualName=ephemeral2"
|
|
||||||
blockDeviceMappings+=" DeviceName=/dev/sde,VirtualName=ephemeral3"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $type = hvm ]; then
|
|
||||||
extraFlags+=" --sriov-net-support simple"
|
|
||||||
extraFlags+=" --ena-support"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Register the AMI.
|
|
||||||
if [ $type = pv ]; then
|
|
||||||
kernel=$(aws ec2 describe-images --owner amazon --filters "Name=name,Values=pv-grub-hd0_1.05-$arch.gz" | jq -r .Images[0].ImageId)
|
|
||||||
if [ "$kernel" = null ]; then break; fi
|
|
||||||
echo "using PV-GRUB kernel $kernel"
|
|
||||||
extraFlags+=" --virtualization-type paravirtual --kernel $kernel"
|
|
||||||
else
|
|
||||||
extraFlags+=" --virtualization-type hvm"
|
|
||||||
fi
|
|
||||||
|
|
||||||
ami=$(aws ec2 register-image \
|
|
||||||
--name "$name" \
|
|
||||||
--description "$description" \
|
|
||||||
--region "$region" \
|
|
||||||
--architecture "$arch" \
|
|
||||||
--block-device-mappings $blockDeviceMappings \
|
|
||||||
$extraFlags | jq -r .ImageId)
|
|
||||||
if [ "$ami" = null ]; then break; fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -n "$ami" > $amiFile
|
|
||||||
echo "created AMI $ami of type '$type' in $region..."
|
|
||||||
|
|
||||||
else
|
|
||||||
ami=$(cat $amiFile)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "region = $region, type = $type, store = $store, ami = $ami"
|
|
||||||
|
|
||||||
if [ -z "$prevAmi" ]; then
|
|
||||||
prevAmi="$ami"
|
|
||||||
prevRegion="$region"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
for type in $types; do
|
|
||||||
link=$stateDir/$type
|
|
||||||
system=x86_64-linux
|
|
||||||
arch=x86_64
|
|
||||||
|
|
||||||
for store in $stores; do
|
|
||||||
|
|
||||||
for region in $regions; do
|
|
||||||
|
|
||||||
name=nixos-$version-$arch-$type-$store
|
|
||||||
amiFile=$stateDir/$region.$type.$store.ami-id
|
|
||||||
ami=$(cat $amiFile)
|
|
||||||
|
|
||||||
echo "region = $region, type = $type, store = $store, ami = $ami"
|
|
||||||
|
|
||||||
echo -n "waiting for AMI..."
|
|
||||||
while true; do
|
|
||||||
status=$(aws ec2 describe-images --image-ids "$ami" --region "$region" | jq -r .Images[0].State)
|
|
||||||
if [ "$status" = available ]; then break; fi
|
|
||||||
sleep 10
|
|
||||||
echo -n '.'
|
|
||||||
done
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Make the image public.
|
|
||||||
aws ec2 modify-image-attribute \
|
aws ec2 modify-image-attribute \
|
||||||
--image-id "$ami" --region "$region" --launch-permission 'Add={Group=all}'
|
--image-id "$ami_id" --region "$region" --launch-permission 'Add={Group=all}' >&2
|
||||||
|
}
|
||||||
|
|
||||||
echo " \"$major\".$region.$type-$store = \"$ami\";" >> ec2-amis.nix
|
upload_image() {
|
||||||
done
|
local region=$1
|
||||||
|
|
||||||
done
|
local aws_path=${image_file#/}
|
||||||
|
|
||||||
|
local state_key="$region.$image_label.$image_system"
|
||||||
|
local task_id=$(read_state "$state_key" task_id)
|
||||||
|
local snapshot_id=$(read_state "$state_key" snapshot_id)
|
||||||
|
local ami_id=$(read_state "$state_key" ami_id)
|
||||||
|
|
||||||
|
if [ -z "$task_id" ]; then
|
||||||
|
log "Checking for image on S3"
|
||||||
|
if ! aws s3 ls --region "$region" "s3://${bucket}/${aws_path}" >&2; then
|
||||||
|
log "Image missing from aws, uploading"
|
||||||
|
aws s3 cp --region $region "$image_file" "s3://${bucket}/${aws_path}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Importing image from S3 path s3://$bucket/$aws_path"
|
||||||
|
|
||||||
|
task_id=$(aws ec2 import-snapshot --disk-container "{
|
||||||
|
\"Description\": \"nixos-image-${image_label}-${image_system}\",
|
||||||
|
\"Format\": \"vhd\",
|
||||||
|
\"UserBucket\": {
|
||||||
|
\"S3Bucket\": \"$bucket\",
|
||||||
|
\"S3Key\": \"$aws_path\"
|
||||||
|
}
|
||||||
|
}" --region $region | jq -r '.ImportTaskId')
|
||||||
|
|
||||||
|
write_state "$state_key" task_id "$task_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$snapshot_id" ]; then
|
||||||
|
snapshot_id=$(wait_for_import "$region" "$task_id")
|
||||||
|
write_state "$state_key" snapshot_id "$snapshot_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$ami_id" ]; then
|
||||||
|
log "Registering snapshot $snapshot_id as AMI"
|
||||||
|
|
||||||
|
local block_device_mappings=(
|
||||||
|
"DeviceName=/dev/sda1,Ebs={SnapshotId=$snapshot_id,VolumeSize=$image_logical_gigabytes,DeleteOnTermination=true,VolumeType=gp2}"
|
||||||
|
)
|
||||||
|
|
||||||
|
local extra_flags=(
|
||||||
|
--root-device-name /dev/sda1
|
||||||
|
--sriov-net-support simple
|
||||||
|
--ena-support
|
||||||
|
--virtualization-type hvm
|
||||||
|
)
|
||||||
|
|
||||||
|
block_device_mappings+=(DeviceName=/dev/sdb,VirtualName=ephemeral0)
|
||||||
|
block_device_mappings+=(DeviceName=/dev/sdc,VirtualName=ephemeral1)
|
||||||
|
block_device_mappings+=(DeviceName=/dev/sdd,VirtualName=ephemeral2)
|
||||||
|
block_device_mappings+=(DeviceName=/dev/sde,VirtualName=ephemeral3)
|
||||||
|
|
||||||
|
ami_id=$(
|
||||||
|
aws ec2 register-image \
|
||||||
|
--name "$image_name" \
|
||||||
|
--description "$image_description" \
|
||||||
|
--region $region \
|
||||||
|
--architecture $amazon_arch \
|
||||||
|
--block-device-mappings "${block_device_mappings[@]}" \
|
||||||
|
"${extra_flags[@]}" \
|
||||||
|
| jq -r '.ImageId'
|
||||||
|
)
|
||||||
|
|
||||||
|
write_state "$state_key" ami_id "$ami_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
make_image_public $region "$ami_id"
|
||||||
|
|
||||||
|
echo "$ami_id"
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_to_region() {
|
||||||
|
local region=$1
|
||||||
|
local from_region=$2
|
||||||
|
local from_ami_id=$3
|
||||||
|
|
||||||
|
state_key="$region.$image_label.$image_system"
|
||||||
|
ami_id=$(read_state "$state_key" ami_id)
|
||||||
|
|
||||||
|
if [ -z "$ami_id" ]; then
|
||||||
|
log "Copying $from_ami_id to $region"
|
||||||
|
ami_id=$(
|
||||||
|
aws ec2 copy-image \
|
||||||
|
--region "$region" \
|
||||||
|
--source-region "$from_region" \
|
||||||
|
--source-image-id "$from_ami_id" \
|
||||||
|
--name "$image_name" \
|
||||||
|
--description "$image_description" \
|
||||||
|
| jq -r '.ImageId'
|
||||||
|
)
|
||||||
|
|
||||||
|
write_state "$state_key" ami_id "$ami_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
make_image_public $region "$ami_id"
|
||||||
|
|
||||||
|
echo "$ami_id"
|
||||||
|
}
|
||||||
|
|
||||||
|
upload_all() {
|
||||||
|
home_image_id=$(upload_image "$home_region")
|
||||||
|
jq -n \
|
||||||
|
--arg key "$home_region.$image_system" \
|
||||||
|
--arg value "$home_image_id" \
|
||||||
|
'$ARGS.named'
|
||||||
|
|
||||||
|
for region in "${regions[@]}"; do
|
||||||
|
if [ "$region" = "$home_region" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
copied_image_id=$(copy_to_region "$region" "$home_region" "$home_image_id")
|
||||||
|
|
||||||
|
jq -n \
|
||||||
|
--arg key "$region.$image_system" \
|
||||||
|
--arg value "$copied_image_id" \
|
||||||
|
'$ARGS.named'
|
||||||
done
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
upload_all | jq --slurp from_entries
|
||||||
|
|
|
@ -7,7 +7,7 @@ with lib;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = config.services.xserver.enable;
|
default = config.services.xserver.enable;
|
||||||
description = ''
|
description = ''
|
||||||
Whether to build icon theme caches for GTK+ applications.
|
Whether to build icon theme caches for GTK applications.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
x86_64-linux = "/nix/store/hbhdjn5ik3byg642d1m11k3k3s0kn3py-nix-2.2.2";
|
x86_64-linux = "/nix/store/3ds3cgji9vjxdbgp10av6smyym1126d1-nix-2.3";
|
||||||
i686-linux = "/nix/store/fz5cikwvj3n0a6zl44h6l2z3cin64mda-nix-2.2.2";
|
i686-linux = "/nix/store/ln1ndqvfpc9cdl03vqxi6kvlxm9wfv9g-nix-2.3";
|
||||||
aarch64-linux = "/nix/store/2gba4cyl4wvxzfbhmli90jy4n5aj0kjj-nix-2.2.2";
|
aarch64-linux = "/nix/store/n8a1rwzrp20qcr2c4hvyn6c5q9zx8csw-nix-2.3";
|
||||||
x86_64-darwin = "/nix/store/87i4fp46jfw9yl8c7i9gx75m5yph7irl-nix-2.2.2";
|
x86_64-darwin = "/nix/store/jq6npmpld02sz4rgniz0qrsdfnm6j17a-nix-2.3";
|
||||||
}
|
}
|
||||||
|
|
|
@ -948,6 +948,7 @@
|
||||||
./virtualisation/openvswitch.nix
|
./virtualisation/openvswitch.nix
|
||||||
./virtualisation/parallels-guest.nix
|
./virtualisation/parallels-guest.nix
|
||||||
./virtualisation/qemu-guest-agent.nix
|
./virtualisation/qemu-guest-agent.nix
|
||||||
|
./virtualisation/railcar.nix
|
||||||
./virtualisation/rkt.nix
|
./virtualisation/rkt.nix
|
||||||
./virtualisation/virtualbox-guest.nix
|
./virtualisation/virtualbox-guest.nix
|
||||||
./virtualisation/virtualbox-host.nix
|
./virtualisation/virtualbox-host.nix
|
||||||
|
|
|
@ -18,7 +18,7 @@ in
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
Whether to enable the Plotinus GTK+3 plugin. Plotinus provides a
|
Whether to enable the Plotinus GTK 3 plugin. Plotinus provides a
|
||||||
popup (triggered by Ctrl-Shift-P) to search the menus of a
|
popup (triggered by Ctrl-Shift-P) to search the menus of a
|
||||||
compatible application.
|
compatible application.
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
<link xlink:href="https://github.com/p-e-w/plotinus"/>
|
<link xlink:href="https://github.com/p-e-w/plotinus"/>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Plotinus is a searchable command palette in every modern GTK+ application.
|
Plotinus is a searchable command palette in every modern GTK application.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
When in a GTK+3 application and Plotinus is enabled, you can press
|
When in a GTK 3 application and Plotinus is enabled, you can press
|
||||||
<literal>Ctrl+Shift+P</literal> to open the command palette. The command
|
<literal>Ctrl+Shift+P</literal> to open the command palette. The command
|
||||||
palette provides a searchable list of of all menu items in the application.
|
palette provides a searchable list of of all menu items in the application.
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -34,6 +34,7 @@ with lib;
|
||||||
(mkRenamedOptionModule [ "services" "kubernetes" "etcd" "caFile" ] [ "services" "kubernetes" "apiserver" "etcd" "caFile" ])
|
(mkRenamedOptionModule [ "services" "kubernetes" "etcd" "caFile" ] [ "services" "kubernetes" "apiserver" "etcd" "caFile" ])
|
||||||
(mkRemovedOptionModule [ "services" "kubernetes" "kubelet" "applyManifests" ] "")
|
(mkRemovedOptionModule [ "services" "kubernetes" "kubelet" "applyManifests" ] "")
|
||||||
(mkRemovedOptionModule [ "services" "kubernetes" "kubelet" "cadvisorPort" ] "")
|
(mkRemovedOptionModule [ "services" "kubernetes" "kubelet" "cadvisorPort" ] "")
|
||||||
|
(mkRemovedOptionModule [ "services" "kubernetes" "kubelet" "allowPrivileged" ] "")
|
||||||
(mkRenamedOptionModule [ "services" "kubernetes" "proxy" "address" ] ["services" "kubernetes" "proxy" "bindAddress"])
|
(mkRenamedOptionModule [ "services" "kubernetes" "proxy" "address" ] ["services" "kubernetes" "proxy" "bindAddress"])
|
||||||
(mkRemovedOptionModule [ "services" "kubernetes" "verbose" ] "")
|
(mkRemovedOptionModule [ "services" "kubernetes" "verbose" ] "")
|
||||||
(mkRenamedOptionModule [ "services" "logstash" "address" ] [ "services" "logstash" "listenAddress" ])
|
(mkRenamedOptionModule [ "services" "logstash" "address" ] [ "services" "logstash" "listenAddress" ])
|
||||||
|
|
|
@ -62,50 +62,19 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
enable = mkEnableOption "Kubernetes addon manager";
|
enable = mkEnableOption "Whether to enable Kubernetes addon manager.";
|
||||||
|
|
||||||
kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes addon manager";
|
|
||||||
bootstrapAddonsKubeconfig = top.lib.mkKubeConfigOptions "Kubernetes addon manager bootstrap";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
config = let
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
addonManagerPaths = filter (a: a != null) [
|
|
||||||
cfg.kubeconfig.caFile
|
|
||||||
cfg.kubeconfig.certFile
|
|
||||||
cfg.kubeconfig.keyFile
|
|
||||||
];
|
|
||||||
bootstrapAddonsPaths = filter (a: a != null) [
|
|
||||||
cfg.bootstrapAddonsKubeconfig.caFile
|
|
||||||
cfg.bootstrapAddonsKubeconfig.certFile
|
|
||||||
cfg.bootstrapAddonsKubeconfig.keyFile
|
|
||||||
];
|
|
||||||
|
|
||||||
in mkIf cfg.enable {
|
|
||||||
environment.etc."kubernetes/addons".source = "${addons}/";
|
environment.etc."kubernetes/addons".source = "${addons}/";
|
||||||
|
|
||||||
#TODO: Get rid of kube-addon-manager in the future for the following reasons
|
|
||||||
# - it is basically just a shell script wrapped around kubectl
|
|
||||||
# - it assumes that it is clusterAdmin or can gain clusterAdmin rights through serviceAccount
|
|
||||||
# - it is designed to be used with k8s system components only
|
|
||||||
# - it would be better with a more Nix-oriented way of managing addons
|
|
||||||
systemd.services.kube-addon-manager = {
|
systemd.services.kube-addon-manager = {
|
||||||
description = "Kubernetes addon manager";
|
description = "Kubernetes addon manager";
|
||||||
wantedBy = [ "kubernetes.target" ];
|
wantedBy = [ "kubernetes.target" ];
|
||||||
after = [ "kube-node-online.target" ];
|
after = [ "kube-apiserver.service" ];
|
||||||
before = [ "kubernetes.target" ];
|
environment.ADDON_PATH = "/etc/kubernetes/addons/";
|
||||||
environment = {
|
path = [ pkgs.gawk ];
|
||||||
ADDON_PATH = "/etc/kubernetes/addons/";
|
|
||||||
KUBECONFIG = top.lib.mkKubeConfig "kube-addon-manager" cfg.kubeconfig;
|
|
||||||
};
|
|
||||||
path = with pkgs; [ gawk kubectl ];
|
|
||||||
preStart = ''
|
|
||||||
until kubectl -n kube-system get serviceaccounts/default 2>/dev/null; do
|
|
||||||
echo kubectl -n kube-system get serviceaccounts/default: exit status $?
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Slice = "kubernetes.slice";
|
Slice = "kubernetes.slice";
|
||||||
ExecStart = "${top.package}/bin/kube-addons";
|
ExecStart = "${top.package}/bin/kube-addons";
|
||||||
|
@ -115,52 +84,8 @@ in
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 10;
|
RestartSec = 10;
|
||||||
};
|
};
|
||||||
unitConfig.ConditionPathExists = addonManagerPaths;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.paths.kube-addon-manager = {
|
|
||||||
wantedBy = [ "kube-addon-manager.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = addonManagerPaths;
|
|
||||||
PathChanged = addonManagerPaths;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.kubernetes.addonManager.kubeconfig.server = mkDefault top.apiserverAddress;
|
|
||||||
|
|
||||||
systemd.services.kube-addon-manager-bootstrap = mkIf (top.apiserver.enable && top.addonManager.bootstrapAddons != {}) {
|
|
||||||
wantedBy = [ "kube-control-plane-online.target" ];
|
|
||||||
after = [ "kube-apiserver.service" ];
|
|
||||||
before = [ "kube-control-plane-online.target" ];
|
|
||||||
path = [ pkgs.kubectl ];
|
|
||||||
environment = {
|
|
||||||
KUBECONFIG = top.lib.mkKubeConfig "kube-addon-manager-bootstrap" cfg.bootstrapAddonsKubeconfig;
|
|
||||||
};
|
|
||||||
preStart = with pkgs; let
|
|
||||||
files = mapAttrsToList (n: v: writeText "${n}.json" (builtins.toJSON v))
|
|
||||||
cfg.bootstrapAddons;
|
|
||||||
in ''
|
|
||||||
until kubectl auth can-i '*' '*' -q 2>/dev/null; do
|
|
||||||
echo kubectl auth can-i '*' '*': exit status $?
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
|
|
||||||
kubectl apply -f ${concatStringsSep " \\\n -f " files}
|
|
||||||
'';
|
|
||||||
script = "echo Ok";
|
|
||||||
unitConfig.ConditionPathExists = bootstrapAddonsPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.kube-addon-manager-bootstrap = {
|
|
||||||
wantedBy = [ "kube-addon-manager-bootstrap.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = bootstrapAddonsPaths;
|
|
||||||
PathChanged = bootstrapAddonsPaths;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.kubernetes.addonManager.bootstrapAddonsKubeconfig.server = mkDefault top.apiserverAddress;
|
|
||||||
|
|
||||||
services.kubernetes.addonManager.bootstrapAddons = mkIf isRBACEnabled
|
services.kubernetes.addonManager.bootstrapAddons = mkIf isRBACEnabled
|
||||||
(let
|
(let
|
||||||
name = system:kube-addon-manager;
|
name = system:kube-addon-manager;
|
||||||
|
|
|
@ -169,23 +169,6 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes-dashboard-cm = {
|
|
||||||
apiVersion = "v1";
|
|
||||||
kind = "ConfigMap";
|
|
||||||
metadata = {
|
|
||||||
labels = {
|
|
||||||
k8s-app = "kubernetes-dashboard";
|
|
||||||
# Allows editing resource and makes sure it is created first.
|
|
||||||
"addonmanager.kubernetes.io/mode" = "EnsureExists";
|
|
||||||
};
|
|
||||||
name = "kubernetes-dashboard-settings";
|
|
||||||
namespace = "kube-system";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.kubernetes.addonManager.bootstrapAddons = mkMerge [{
|
|
||||||
|
|
||||||
kubernetes-dashboard-sa = {
|
kubernetes-dashboard-sa = {
|
||||||
apiVersion = "v1";
|
apiVersion = "v1";
|
||||||
kind = "ServiceAccount";
|
kind = "ServiceAccount";
|
||||||
|
@ -227,9 +210,20 @@ in {
|
||||||
};
|
};
|
||||||
type = "Opaque";
|
type = "Opaque";
|
||||||
};
|
};
|
||||||
}
|
kubernetes-dashboard-cm = {
|
||||||
|
apiVersion = "v1";
|
||||||
(optionalAttrs cfg.rbac.enable
|
kind = "ConfigMap";
|
||||||
|
metadata = {
|
||||||
|
labels = {
|
||||||
|
k8s-app = "kubernetes-dashboard";
|
||||||
|
# Allows editing resource and makes sure it is created first.
|
||||||
|
"addonmanager.kubernetes.io/mode" = "EnsureExists";
|
||||||
|
};
|
||||||
|
name = "kubernetes-dashboard-settings";
|
||||||
|
namespace = "kube-system";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // (optionalAttrs cfg.rbac.enable
|
||||||
(let
|
(let
|
||||||
subjects = [{
|
subjects = [{
|
||||||
kind = "ServiceAccount";
|
kind = "ServiceAccount";
|
||||||
|
@ -329,6 +323,6 @@ in {
|
||||||
inherit subjects;
|
inherit subjects;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
))];
|
));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,32 +290,11 @@ in
|
||||||
###### implementation
|
###### implementation
|
||||||
config = mkMerge [
|
config = mkMerge [
|
||||||
|
|
||||||
(let
|
(mkIf cfg.enable {
|
||||||
|
|
||||||
apiserverPaths = filter (a: a != null) [
|
|
||||||
cfg.clientCaFile
|
|
||||||
cfg.etcd.caFile
|
|
||||||
cfg.etcd.certFile
|
|
||||||
cfg.etcd.keyFile
|
|
||||||
cfg.kubeletClientCaFile
|
|
||||||
cfg.kubeletClientCertFile
|
|
||||||
cfg.kubeletClientKeyFile
|
|
||||||
cfg.serviceAccountKeyFile
|
|
||||||
cfg.tlsCertFile
|
|
||||||
cfg.tlsKeyFile
|
|
||||||
];
|
|
||||||
etcdPaths = filter (a: a != null) [
|
|
||||||
config.services.etcd.trustedCaFile
|
|
||||||
config.services.etcd.certFile
|
|
||||||
config.services.etcd.keyFile
|
|
||||||
];
|
|
||||||
|
|
||||||
in mkIf cfg.enable {
|
|
||||||
systemd.services.kube-apiserver = {
|
systemd.services.kube-apiserver = {
|
||||||
description = "Kubernetes APIServer Service";
|
description = "Kubernetes APIServer Service";
|
||||||
wantedBy = [ "kube-control-plane-online.target" ];
|
wantedBy = [ "kubernetes.target" ];
|
||||||
after = [ "certmgr.service" ];
|
after = [ "network.target" ];
|
||||||
before = [ "kube-control-plane-online.target" ];
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Slice = "kubernetes.slice";
|
Slice = "kubernetes.slice";
|
||||||
ExecStart = ''${top.package}/bin/kube-apiserver \
|
ExecStart = ''${top.package}/bin/kube-apiserver \
|
||||||
|
@ -386,15 +365,6 @@ in
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 5;
|
RestartSec = 5;
|
||||||
};
|
};
|
||||||
unitConfig.ConditionPathExists = apiserverPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.kube-apiserver = mkIf top.apiserver.enable {
|
|
||||||
wantedBy = [ "kube-apiserver.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = apiserverPaths;
|
|
||||||
PathChanged = apiserverPaths;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.etcd = {
|
services.etcd = {
|
||||||
|
@ -408,18 +378,6 @@ in
|
||||||
initialAdvertisePeerUrls = mkDefault ["https://${top.masterAddress}:2380"];
|
initialAdvertisePeerUrls = mkDefault ["https://${top.masterAddress}:2380"];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.etcd = {
|
|
||||||
unitConfig.ConditionPathExists = etcdPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.etcd = {
|
|
||||||
wantedBy = [ "etcd.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = etcdPaths;
|
|
||||||
PathChanged = etcdPaths;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.kubernetes.addonManager.bootstrapAddons = mkIf isRBACEnabled {
|
services.kubernetes.addonManager.bootstrapAddons = mkIf isRBACEnabled {
|
||||||
|
|
||||||
apiserver-kubelet-api-admin-crb = {
|
apiserver-kubelet-api-admin-crb = {
|
||||||
|
|
|
@ -104,31 +104,11 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
config = let
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.kube-controller-manager = {
|
||||||
controllerManagerPaths = filter (a: a != null) [
|
|
||||||
cfg.kubeconfig.caFile
|
|
||||||
cfg.kubeconfig.certFile
|
|
||||||
cfg.kubeconfig.keyFile
|
|
||||||
cfg.rootCaFile
|
|
||||||
cfg.serviceAccountKeyFile
|
|
||||||
cfg.tlsCertFile
|
|
||||||
cfg.tlsKeyFile
|
|
||||||
];
|
|
||||||
|
|
||||||
in mkIf cfg.enable {
|
|
||||||
systemd.services.kube-controller-manager = rec {
|
|
||||||
description = "Kubernetes Controller Manager Service";
|
description = "Kubernetes Controller Manager Service";
|
||||||
wantedBy = [ "kube-control-plane-online.target" ];
|
wantedBy = [ "kubernetes.target" ];
|
||||||
after = [ "kube-apiserver.service" ];
|
after = [ "kube-apiserver.service" ];
|
||||||
before = [ "kube-control-plane-online.target" ];
|
|
||||||
environment.KUBECONFIG = top.lib.mkKubeConfig "kube-controller-manager" cfg.kubeconfig;
|
|
||||||
preStart = ''
|
|
||||||
until kubectl auth can-i get /api -q 2>/dev/null; do
|
|
||||||
echo kubectl auth can-i get /api: exit status $?
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
RestartSec = "30s";
|
RestartSec = "30s";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
|
@ -140,7 +120,7 @@ in
|
||||||
"--cluster-cidr=${cfg.clusterCidr}"} \
|
"--cluster-cidr=${cfg.clusterCidr}"} \
|
||||||
${optionalString (cfg.featureGates != [])
|
${optionalString (cfg.featureGates != [])
|
||||||
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
||||||
--kubeconfig=${environment.KUBECONFIG} \
|
--kubeconfig=${top.lib.mkKubeConfig "kube-controller-manager" cfg.kubeconfig} \
|
||||||
--leader-elect=${boolToString cfg.leaderElect} \
|
--leader-elect=${boolToString cfg.leaderElect} \
|
||||||
${optionalString (cfg.rootCaFile!=null)
|
${optionalString (cfg.rootCaFile!=null)
|
||||||
"--root-ca-file=${cfg.rootCaFile}"} \
|
"--root-ca-file=${cfg.rootCaFile}"} \
|
||||||
|
@ -161,16 +141,7 @@ in
|
||||||
User = "kubernetes";
|
User = "kubernetes";
|
||||||
Group = "kubernetes";
|
Group = "kubernetes";
|
||||||
};
|
};
|
||||||
path = top.path ++ [ pkgs.kubectl ];
|
path = top.path;
|
||||||
unitConfig.ConditionPathExists = controllerManagerPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.kube-controller-manager = {
|
|
||||||
wantedBy = [ "kube-controller-manager.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = controllerManagerPaths;
|
|
||||||
PathChanged = controllerManagerPaths;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.kubernetes.pki.certs = with top.lib; {
|
services.kubernetes.pki.certs = with top.lib; {
|
||||||
|
|
|
@ -256,29 +256,6 @@ in {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.targets.kube-control-plane-online = {
|
|
||||||
wantedBy = [ "kubernetes.target" ];
|
|
||||||
before = [ "kubernetes.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.kube-control-plane-online = {
|
|
||||||
description = "Kubernetes control plane is online";
|
|
||||||
wantedBy = [ "kube-control-plane-online.target" ];
|
|
||||||
after = [ "kube-scheduler.service" "kube-controller-manager.service" ];
|
|
||||||
before = [ "kube-control-plane-online.target" ];
|
|
||||||
path = [ pkgs.curl ];
|
|
||||||
preStart = ''
|
|
||||||
until curl -Ssf ${cfg.apiserverAddress}/healthz do
|
|
||||||
echo curl -Ssf ${cfg.apiserverAddress}/healthz: exit status $?
|
|
||||||
sleep 3
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
script = "echo Ok";
|
|
||||||
serviceConfig = {
|
|
||||||
TimeoutSec = "500";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d /opt/cni/bin 0755 root root -"
|
"d /opt/cni/bin 0755 root root -"
|
||||||
"d /run/kubernetes 0755 kubernetes kubernetes -"
|
"d /run/kubernetes 0755 kubernetes kubernetes -"
|
||||||
|
@ -302,8 +279,6 @@ in {
|
||||||
services.kubernetes.apiserverAddress = mkDefault ("https://${if cfg.apiserver.advertiseAddress != null
|
services.kubernetes.apiserverAddress = mkDefault ("https://${if cfg.apiserver.advertiseAddress != null
|
||||||
then cfg.apiserver.advertiseAddress
|
then cfg.apiserver.advertiseAddress
|
||||||
else "${cfg.masterAddress}:${toString cfg.apiserver.securePort}"}");
|
else "${cfg.masterAddress}:${toString cfg.apiserver.securePort}"}");
|
||||||
|
|
||||||
services.kubernetes.kubeconfig.server = mkDefault cfg.apiserverAddress;
|
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,36 +14,25 @@ let
|
||||||
buildInputs = [ pkgs.makeWrapper ];
|
buildInputs = [ pkgs.makeWrapper ];
|
||||||
} ''
|
} ''
|
||||||
mkdir -p $out
|
mkdir -p $out
|
||||||
cp ${pkgs.kubernetes.src}/cluster/centos/node/bin/mk-docker-opts.sh $out/mk-docker-opts.sh
|
|
||||||
|
|
||||||
# bashInteractive needed for `compgen`
|
# bashInteractive needed for `compgen`
|
||||||
makeWrapper ${pkgs.bashInteractive}/bin/bash $out/mk-docker-opts --add-flags "$out/mk-docker-opts.sh"
|
makeWrapper ${pkgs.bashInteractive}/bin/bash $out/mk-docker-opts --add-flags "${pkgs.kubernetes}/bin/mk-docker-opts.sh"
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
###### interface
|
###### interface
|
||||||
options.services.kubernetes.flannel = {
|
options.services.kubernetes.flannel = {
|
||||||
enable = mkEnableOption "flannel networking";
|
enable = mkEnableOption "enable flannel networking";
|
||||||
kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes flannel";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
config = let
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
flannelPaths = filter (a: a != null) [
|
|
||||||
cfg.kubeconfig.caFile
|
|
||||||
cfg.kubeconfig.certFile
|
|
||||||
cfg.kubeconfig.keyFile
|
|
||||||
];
|
|
||||||
kubeconfig = top.lib.mkKubeConfig "flannel" cfg.kubeconfig;
|
|
||||||
|
|
||||||
in mkIf cfg.enable {
|
|
||||||
services.flannel = {
|
services.flannel = {
|
||||||
|
|
||||||
enable = mkDefault true;
|
enable = mkDefault true;
|
||||||
network = mkDefault top.clusterCidr;
|
network = mkDefault top.clusterCidr;
|
||||||
inherit storageBackend kubeconfig;
|
inherit storageBackend;
|
||||||
nodeName = top.kubelet.hostname;
|
nodeName = config.services.kubernetes.kubelet.hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.kubernetes.kubelet = {
|
services.kubernetes.kubelet = {
|
||||||
|
@ -58,66 +47,24 @@ in
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.mk-docker-opts = {
|
systemd.services."mk-docker-opts" = {
|
||||||
description = "Pre-Docker Actions";
|
description = "Pre-Docker Actions";
|
||||||
wantedBy = [ "flannel.target" ];
|
|
||||||
before = [ "flannel.target" ];
|
|
||||||
path = with pkgs; [ gawk gnugrep ];
|
path = with pkgs; [ gawk gnugrep ];
|
||||||
script = ''
|
script = ''
|
||||||
${mkDockerOpts}/mk-docker-opts -d /run/flannel/docker
|
${mkDockerOpts}/mk-docker-opts -d /run/flannel/docker
|
||||||
systemctl restart docker
|
systemctl restart docker
|
||||||
'';
|
'';
|
||||||
unitConfig.ConditionPathExists = [ "/run/flannel/subnet.env" ];
|
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.paths.flannel-subnet-env = {
|
systemd.paths."flannel-subnet-env" = {
|
||||||
wantedBy = [ "mk-docker-opts.service" ];
|
wantedBy = [ "flannel.service" ];
|
||||||
pathConfig = {
|
pathConfig = {
|
||||||
PathExists = [ "/run/flannel/subnet.env" ];
|
PathModified = "/run/flannel/subnet.env";
|
||||||
PathChanged = [ "/run/flannel/subnet.env" ];
|
|
||||||
Unit = "mk-docker-opts.service";
|
Unit = "mk-docker-opts.service";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.targets.flannel = {
|
|
||||||
wantedBy = [ "kube-node-online.target" ];
|
|
||||||
before = [ "kube-node-online.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.flannel = {
|
|
||||||
wantedBy = [ "flannel.target" ];
|
|
||||||
after = [ "kubelet.target" ];
|
|
||||||
before = [ "flannel.target" ];
|
|
||||||
path = with pkgs; [ iptables kubectl ];
|
|
||||||
environment.KUBECONFIG = kubeconfig;
|
|
||||||
preStart = let
|
|
||||||
args = [
|
|
||||||
"--selector=kubernetes.io/hostname=${top.kubelet.hostname}"
|
|
||||||
# flannel exits if node is not registered yet, before that there is no podCIDR
|
|
||||||
"--output=jsonpath={.items[0].spec.podCIDR}"
|
|
||||||
# if jsonpath cannot be resolved exit with status 1
|
|
||||||
"--allow-missing-template-keys=false"
|
|
||||||
];
|
|
||||||
in ''
|
|
||||||
until kubectl get nodes ${concatStringsSep " " args} 2>/dev/null; do
|
|
||||||
echo Waiting for ${top.kubelet.hostname} to be RegisteredNode
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
unitConfig.ConditionPathExists = flannelPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.flannel = {
|
|
||||||
wantedBy = [ "flannel.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = flannelPaths;
|
|
||||||
PathChanged = flannelPaths;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.kubernetes.flannel.kubeconfig.server = mkDefault top.apiserverAddress;
|
|
||||||
|
|
||||||
systemd.services.docker = {
|
systemd.services.docker = {
|
||||||
environment.DOCKER_OPTS = "-b none";
|
environment.DOCKER_OPTS = "-b none";
|
||||||
serviceConfig.EnvironmentFile = "-/run/flannel/docker";
|
serviceConfig.EnvironmentFile = "-/run/flannel/docker";
|
||||||
|
@ -144,6 +91,7 @@ in
|
||||||
|
|
||||||
# give flannel som kubernetes rbac permissions if applicable
|
# give flannel som kubernetes rbac permissions if applicable
|
||||||
services.kubernetes.addonManager.bootstrapAddons = mkIf ((storageBackend == "kubernetes") && (elem "RBAC" top.apiserver.authorizationMode)) {
|
services.kubernetes.addonManager.bootstrapAddons = mkIf ((storageBackend == "kubernetes") && (elem "RBAC" top.apiserver.authorizationMode)) {
|
||||||
|
|
||||||
flannel-cr = {
|
flannel-cr = {
|
||||||
apiVersion = "rbac.authorization.k8s.io/v1beta1";
|
apiVersion = "rbac.authorization.k8s.io/v1beta1";
|
||||||
kind = "ClusterRole";
|
kind = "ClusterRole";
|
||||||
|
@ -179,6 +127,7 @@ in
|
||||||
name = "flannel-client";
|
name = "flannel-client";
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,12 +61,6 @@ in
|
||||||
type = str;
|
type = str;
|
||||||
};
|
};
|
||||||
|
|
||||||
allowPrivileged = mkOption {
|
|
||||||
description = "Whether to allow Kubernetes containers to request privileged mode.";
|
|
||||||
default = false;
|
|
||||||
type = bool;
|
|
||||||
};
|
|
||||||
|
|
||||||
clusterDns = mkOption {
|
clusterDns = mkOption {
|
||||||
description = "Use alternative DNS.";
|
description = "Use alternative DNS.";
|
||||||
default = "10.1.0.1";
|
default = "10.1.0.1";
|
||||||
|
@ -234,28 +228,21 @@ in
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
config = mkMerge [
|
config = mkMerge [
|
||||||
(let
|
(mkIf cfg.enable {
|
||||||
|
|
||||||
kubeletPaths = filter (a: a != null) [
|
|
||||||
cfg.kubeconfig.caFile
|
|
||||||
cfg.kubeconfig.certFile
|
|
||||||
cfg.kubeconfig.keyFile
|
|
||||||
cfg.clientCaFile
|
|
||||||
cfg.tlsCertFile
|
|
||||||
cfg.tlsKeyFile
|
|
||||||
];
|
|
||||||
|
|
||||||
in mkIf cfg.enable {
|
|
||||||
services.kubernetes.kubelet.seedDockerImages = [infraContainer];
|
services.kubernetes.kubelet.seedDockerImages = [infraContainer];
|
||||||
|
|
||||||
systemd.services.kubelet = {
|
systemd.services.kubelet = {
|
||||||
description = "Kubernetes Kubelet Service";
|
description = "Kubernetes Kubelet Service";
|
||||||
wantedBy = [ "kubelet.target" ];
|
wantedBy = [ "kubernetes.target" ];
|
||||||
after = [ "kube-control-plane-online.target" ];
|
after = [ "network.target" "docker.service" "kube-apiserver.service" ];
|
||||||
before = [ "kubelet.target" ];
|
|
||||||
path = with pkgs; [ gitMinimal openssh docker utillinux iproute ethtool thin-provisioning-tools iptables socat ] ++ top.path;
|
path = with pkgs; [ gitMinimal openssh docker utillinux iproute ethtool thin-provisioning-tools iptables socat ] ++ top.path;
|
||||||
preStart = ''
|
preStart = ''
|
||||||
rm -f /opt/cni/bin/* || true
|
${concatMapStrings (img: ''
|
||||||
|
echo "Seeding docker image: ${img}"
|
||||||
|
docker load <${img}
|
||||||
|
'') cfg.seedDockerImages}
|
||||||
|
|
||||||
|
rm /opt/cni/bin/* || true
|
||||||
${concatMapStrings (package: ''
|
${concatMapStrings (package: ''
|
||||||
echo "Linking cni package: ${package}"
|
echo "Linking cni package: ${package}"
|
||||||
ln -fs ${package}/bin/* /opt/cni/bin
|
ln -fs ${package}/bin/* /opt/cni/bin
|
||||||
|
@ -269,7 +256,6 @@ in
|
||||||
RestartSec = "1000ms";
|
RestartSec = "1000ms";
|
||||||
ExecStart = ''${top.package}/bin/kubelet \
|
ExecStart = ''${top.package}/bin/kubelet \
|
||||||
--address=${cfg.address} \
|
--address=${cfg.address} \
|
||||||
--allow-privileged=${boolToString cfg.allowPrivileged} \
|
|
||||||
--authentication-token-webhook \
|
--authentication-token-webhook \
|
||||||
--authentication-token-webhook-cache-ttl="10s" \
|
--authentication-token-webhook-cache-ttl="10s" \
|
||||||
--authorization-mode=Webhook \
|
--authorization-mode=Webhook \
|
||||||
|
@ -308,56 +294,6 @@ in
|
||||||
'';
|
'';
|
||||||
WorkingDirectory = top.dataDir;
|
WorkingDirectory = top.dataDir;
|
||||||
};
|
};
|
||||||
unitConfig.ConditionPathExists = kubeletPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.kubelet = {
|
|
||||||
wantedBy = [ "kubelet.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = kubeletPaths;
|
|
||||||
PathChanged = kubeletPaths;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.docker.before = [ "kubelet.service" ];
|
|
||||||
|
|
||||||
systemd.services.docker-seed-images = {
|
|
||||||
wantedBy = [ "docker.service" ];
|
|
||||||
after = [ "docker.service" ];
|
|
||||||
before = [ "kubelet.service" ];
|
|
||||||
path = with pkgs; [ docker ];
|
|
||||||
preStart = ''
|
|
||||||
${concatMapStrings (img: ''
|
|
||||||
echo "Seeding docker image: ${img}"
|
|
||||||
docker load <${img}
|
|
||||||
'') cfg.seedDockerImages}
|
|
||||||
'';
|
|
||||||
script = "echo Ok";
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
serviceConfig.RemainAfterExit = true;
|
|
||||||
serviceConfig.Slice = "kubernetes.slice";
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.kubelet-online = {
|
|
||||||
wantedBy = [ "kube-node-online.target" ];
|
|
||||||
after = [ "flannel.target" "kubelet.target" ];
|
|
||||||
before = [ "kube-node-online.target" ];
|
|
||||||
# it is complicated. flannel needs kubelet to run the pause container before
|
|
||||||
# it discusses the node CIDR with apiserver and afterwards configures and restarts
|
|
||||||
# dockerd. Until then prevent creating any pods because they have to be recreated anyway
|
|
||||||
# because the network of docker0 has been changed by flannel.
|
|
||||||
script = let
|
|
||||||
docker-env = "/run/flannel/docker";
|
|
||||||
flannel-date = "stat --print=%Y ${docker-env}";
|
|
||||||
docker-date = "systemctl show --property=ActiveEnterTimestamp --value docker";
|
|
||||||
in ''
|
|
||||||
until test -f ${docker-env} ; do sleep 1 ; done
|
|
||||||
while test `${flannel-date}` -gt `date +%s --date="$(${docker-date})"` ; do
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
serviceConfig.Slice = "kubernetes.slice";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Allways include cni plugins
|
# Allways include cni plugins
|
||||||
|
@ -404,16 +340,5 @@ in
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
{
|
|
||||||
systemd.targets.kubelet = {
|
|
||||||
wantedBy = [ "kube-node-online.target" ];
|
|
||||||
before = [ "kube-node-online.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.targets.kube-node-online = {
|
|
||||||
wantedBy = [ "kubernetes.target" ];
|
|
||||||
before = [ "kubernetes.target" ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@ let
|
||||||
certmgrAPITokenPath = "${top.secretsPath}/${cfsslAPITokenBaseName}";
|
certmgrAPITokenPath = "${top.secretsPath}/${cfsslAPITokenBaseName}";
|
||||||
cfsslAPITokenLength = 32;
|
cfsslAPITokenLength = 32;
|
||||||
|
|
||||||
clusterAdminKubeconfig = with cfg.certs.clusterAdmin; {
|
clusterAdminKubeconfig = with cfg.certs.clusterAdmin;
|
||||||
|
top.lib.mkKubeConfig "cluster-admin" {
|
||||||
server = top.apiserverAddress;
|
server = top.apiserverAddress;
|
||||||
certFile = cert;
|
certFile = cert;
|
||||||
keyFile = key;
|
keyFile = key;
|
||||||
|
@ -118,11 +119,6 @@ in
|
||||||
cfsslCertPathPrefix = "${config.services.cfssl.dataDir}/cfssl";
|
cfsslCertPathPrefix = "${config.services.cfssl.dataDir}/cfssl";
|
||||||
cfsslCert = "${cfsslCertPathPrefix}.pem";
|
cfsslCert = "${cfsslCertPathPrefix}.pem";
|
||||||
cfsslKey = "${cfsslCertPathPrefix}-key.pem";
|
cfsslKey = "${cfsslCertPathPrefix}-key.pem";
|
||||||
|
|
||||||
certmgrPaths = [
|
|
||||||
top.caFile
|
|
||||||
certmgrAPITokenPath
|
|
||||||
];
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -172,40 +168,13 @@ in
|
||||||
chown cfssl "${cfsslAPITokenPath}" && chmod 400 "${cfsslAPITokenPath}"
|
chown cfssl "${cfsslAPITokenPath}" && chmod 400 "${cfsslAPITokenPath}"
|
||||||
'')]);
|
'')]);
|
||||||
|
|
||||||
systemd.targets.cfssl-online = {
|
|
||||||
wantedBy = [ "network-online.target" ];
|
|
||||||
after = [ "cfssl.service" "network-online.target" "cfssl-online.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.cfssl-online = {
|
|
||||||
description = "Wait for ${remote} to be reachable.";
|
|
||||||
wantedBy = [ "cfssl-online.target" ];
|
|
||||||
before = [ "cfssl-online.target" ];
|
|
||||||
path = [ pkgs.curl ];
|
|
||||||
preStart = ''
|
|
||||||
until curl --fail-early -fskd '{}' ${remote}/api/v1/cfssl/info -o /dev/null; do
|
|
||||||
echo curl ${remote}/api/v1/cfssl/info: exit status $?
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
script = "echo Ok";
|
|
||||||
serviceConfig = {
|
|
||||||
TimeoutSec = "300";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.kube-certmgr-bootstrap = {
|
systemd.services.kube-certmgr-bootstrap = {
|
||||||
description = "Kubernetes certmgr bootstrapper";
|
description = "Kubernetes certmgr bootstrapper";
|
||||||
wantedBy = [ "cfssl-online.target" ];
|
wantedBy = [ "certmgr.service" ];
|
||||||
after = [ "cfssl-online.target" ];
|
after = [ "cfssl.target" ];
|
||||||
before = [ "certmgr.service" ];
|
|
||||||
path = with pkgs; [ curl cfssl ];
|
|
||||||
script = concatStringsSep "\n" [''
|
script = concatStringsSep "\n" [''
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
mkdir -p $(dirname ${certmgrAPITokenPath})
|
|
||||||
mkdir -p $(dirname ${top.caFile})
|
|
||||||
|
|
||||||
# If there's a cfssl (cert issuer) running locally, then don't rely on user to
|
# If there's a cfssl (cert issuer) running locally, then don't rely on user to
|
||||||
# manually paste it in place. Just symlink.
|
# manually paste it in place. Just symlink.
|
||||||
# otherwise, create the target file, ready for users to insert the token
|
# otherwise, create the target file, ready for users to insert the token
|
||||||
|
@ -217,18 +186,15 @@ in
|
||||||
fi
|
fi
|
||||||
''
|
''
|
||||||
(optionalString (cfg.pkiTrustOnBootstrap) ''
|
(optionalString (cfg.pkiTrustOnBootstrap) ''
|
||||||
if [ ! -s "${top.caFile}" ]; then
|
if [ ! -f "${top.caFile}" ] || [ $(cat "${top.caFile}" | wc -c) -lt 1 ]; then
|
||||||
until test -s ${top.caFile}.json; do
|
${pkgs.curl}/bin/curl --fail-early -f -kd '{}' ${remote}/api/v1/cfssl/info | \
|
||||||
sleep 2
|
${pkgs.cfssl}/bin/cfssljson -stdout >${top.caFile}
|
||||||
curl --fail-early -fskd '{}' ${remote}/api/v1/cfssl/info -o ${top.caFile}.json
|
|
||||||
done
|
|
||||||
cfssljson -f ${top.caFile}.json -stdout >${top.caFile}
|
|
||||||
rm ${top.caFile}.json
|
|
||||||
fi
|
fi
|
||||||
'')
|
'')
|
||||||
];
|
];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
TimeoutSec = "500";
|
RestartSec = "10s";
|
||||||
|
Restart = "on-failure";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -264,28 +230,35 @@ in
|
||||||
mapAttrs mkSpec cfg.certs;
|
mapAttrs mkSpec cfg.certs;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.certmgr = {
|
#TODO: Get rid of kube-addon-manager in the future for the following reasons
|
||||||
wantedBy = [ "cfssl-online.target" ];
|
# - it is basically just a shell script wrapped around kubectl
|
||||||
after = [ "cfssl-online.target" "kube-certmgr-bootstrap.service" ];
|
# - it assumes that it is clusterAdmin or can gain clusterAdmin rights through serviceAccount
|
||||||
preStart = ''
|
# - it is designed to be used with k8s system components only
|
||||||
while ! test -s ${certmgrAPITokenPath} ; do
|
# - it would be better with a more Nix-oriented way of managing addons
|
||||||
sleep 1
|
systemd.services.kube-addon-manager = mkIf top.addonManager.enable (mkMerge [{
|
||||||
echo Waiting for ${certmgrAPITokenPath}
|
environment.KUBECONFIG = with cfg.certs.addonManager;
|
||||||
done
|
top.lib.mkKubeConfig "addon-manager" {
|
||||||
|
server = top.apiserverAddress;
|
||||||
|
certFile = cert;
|
||||||
|
keyFile = key;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
(optionalAttrs (top.addonManager.bootstrapAddons != {}) {
|
||||||
|
serviceConfig.PermissionsStartOnly = true;
|
||||||
|
preStart = with pkgs;
|
||||||
|
let
|
||||||
|
files = mapAttrsToList (n: v: writeText "${n}.json" (builtins.toJSON v))
|
||||||
|
top.addonManager.bootstrapAddons;
|
||||||
|
in
|
||||||
|
''
|
||||||
|
export KUBECONFIG=${clusterAdminKubeconfig}
|
||||||
|
${kubectl}/bin/kubectl apply -f ${concatStringsSep " \\\n -f " files}
|
||||||
'';
|
'';
|
||||||
unitConfig.ConditionPathExists = certmgrPaths;
|
})]);
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.certmgr = {
|
environment.etc.${cfg.etcClusterAdminKubeconfig}.source = mkIf (!isNull cfg.etcClusterAdminKubeconfig)
|
||||||
wantedBy = [ "certmgr.service" ];
|
clusterAdminKubeconfig;
|
||||||
pathConfig = {
|
|
||||||
PathExists = certmgrPaths;
|
|
||||||
PathChanged = certmgrPaths;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.etc.${cfg.etcClusterAdminKubeconfig}.source = mkIf (cfg.etcClusterAdminKubeconfig != null)
|
|
||||||
(top.lib.mkKubeConfig "cluster-admin" clusterAdminKubeconfig);
|
|
||||||
|
|
||||||
environment.systemPackages = mkIf (top.kubelet.enable || top.proxy.enable) [
|
environment.systemPackages = mkIf (top.kubelet.enable || top.proxy.enable) [
|
||||||
(pkgs.writeScriptBin "nixos-kubernetes-node-join" ''
|
(pkgs.writeScriptBin "nixos-kubernetes-node-join" ''
|
||||||
|
@ -311,22 +284,38 @@ in
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
do_restart=$(test -s ${certmgrAPITokenPath} && echo -n y || echo -n n)
|
|
||||||
|
|
||||||
echo $token > ${certmgrAPITokenPath}
|
echo $token > ${certmgrAPITokenPath}
|
||||||
chmod 600 ${certmgrAPITokenPath}
|
chmod 600 ${certmgrAPITokenPath}
|
||||||
|
|
||||||
if [ y = $do_restart ]; then
|
|
||||||
echo "Restarting certmgr..." >&1
|
echo "Restarting certmgr..." >&1
|
||||||
systemctl restart certmgr
|
systemctl restart certmgr
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Node joined succesfully" >&1
|
echo "Waiting for certs to appear..." >&1
|
||||||
|
|
||||||
|
${optionalString top.kubelet.enable ''
|
||||||
|
while [ ! -f ${cfg.certs.kubelet.cert} ]; do sleep 1; done
|
||||||
|
echo "Restarting kubelet..." >&1
|
||||||
|
systemctl restart kubelet
|
||||||
|
''}
|
||||||
|
|
||||||
|
${optionalString top.proxy.enable ''
|
||||||
|
while [ ! -f ${cfg.certs.kubeProxyClient.cert} ]; do sleep 1; done
|
||||||
|
echo "Restarting kube-proxy..." >&1
|
||||||
|
systemctl restart kube-proxy
|
||||||
|
''}
|
||||||
|
|
||||||
|
${optionalString top.flannel.enable ''
|
||||||
|
while [ ! -f ${cfg.certs.flannelClient.cert} ]; do sleep 1; done
|
||||||
|
echo "Restarting flannel..." >&1
|
||||||
|
systemctl restart flannel
|
||||||
|
''}
|
||||||
|
|
||||||
|
echo "Node joined succesfully"
|
||||||
'')];
|
'')];
|
||||||
|
|
||||||
# isolate etcd on loopback at the master node
|
# isolate etcd on loopback at the master node
|
||||||
# easyCerts doesn't support multimaster clusters anyway atm.
|
# easyCerts doesn't support multimaster clusters anyway atm.
|
||||||
services.etcd = mkIf top.apiserver.enable (with cfg.certs.etcd; {
|
services.etcd = with cfg.certs.etcd; {
|
||||||
listenClientUrls = ["https://127.0.0.1:2379"];
|
listenClientUrls = ["https://127.0.0.1:2379"];
|
||||||
listenPeerUrls = ["https://127.0.0.1:2380"];
|
listenPeerUrls = ["https://127.0.0.1:2380"];
|
||||||
advertiseClientUrls = ["https://etcd.local:2379"];
|
advertiseClientUrls = ["https://etcd.local:2379"];
|
||||||
|
@ -335,11 +324,19 @@ in
|
||||||
certFile = mkDefault cert;
|
certFile = mkDefault cert;
|
||||||
keyFile = mkDefault key;
|
keyFile = mkDefault key;
|
||||||
trustedCaFile = mkDefault caCert;
|
trustedCaFile = mkDefault caCert;
|
||||||
});
|
};
|
||||||
networking.extraHosts = mkIf (config.services.etcd.enable) ''
|
networking.extraHosts = mkIf (config.services.etcd.enable) ''
|
||||||
127.0.0.1 etcd.${top.addons.dns.clusterDomain} etcd.local
|
127.0.0.1 etcd.${top.addons.dns.clusterDomain} etcd.local
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
services.flannel = with cfg.certs.flannelClient; {
|
||||||
|
kubeconfig = top.lib.mkKubeConfig "flannel" {
|
||||||
|
server = top.apiserverAddress;
|
||||||
|
certFile = cert;
|
||||||
|
keyFile = key;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
services.kubernetes = {
|
services.kubernetes = {
|
||||||
|
|
||||||
apiserver = mkIf top.apiserver.enable (with cfg.certs.apiServer; {
|
apiserver = mkIf top.apiserver.enable (with cfg.certs.apiServer; {
|
||||||
|
@ -359,13 +356,6 @@ in
|
||||||
proxyClientCertFile = mkDefault cfg.certs.apiserverProxyClient.cert;
|
proxyClientCertFile = mkDefault cfg.certs.apiserverProxyClient.cert;
|
||||||
proxyClientKeyFile = mkDefault cfg.certs.apiserverProxyClient.key;
|
proxyClientKeyFile = mkDefault cfg.certs.apiserverProxyClient.key;
|
||||||
});
|
});
|
||||||
addonManager = mkIf top.addonManager.enable {
|
|
||||||
kubeconfig = with cfg.certs.addonManager; {
|
|
||||||
certFile = mkDefault cert;
|
|
||||||
keyFile = mkDefault key;
|
|
||||||
};
|
|
||||||
bootstrapAddonsKubeconfig = clusterAdminKubeconfig;
|
|
||||||
};
|
|
||||||
controllerManager = mkIf top.controllerManager.enable {
|
controllerManager = mkIf top.controllerManager.enable {
|
||||||
serviceAccountKeyFile = mkDefault cfg.certs.serviceAccount.key;
|
serviceAccountKeyFile = mkDefault cfg.certs.serviceAccount.key;
|
||||||
rootCaFile = cfg.certs.controllerManagerClient.caCert;
|
rootCaFile = cfg.certs.controllerManagerClient.caCert;
|
||||||
|
@ -374,12 +364,6 @@ in
|
||||||
keyFile = mkDefault key;
|
keyFile = mkDefault key;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
flannel = mkIf top.flannel.enable {
|
|
||||||
kubeconfig = with cfg.certs.flannelClient; {
|
|
||||||
certFile = cert;
|
|
||||||
keyFile = key;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
scheduler = mkIf top.scheduler.enable {
|
scheduler = mkIf top.scheduler.enable {
|
||||||
kubeconfig = with cfg.certs.schedulerClient; {
|
kubeconfig = with cfg.certs.schedulerClient; {
|
||||||
certFile = mkDefault cert;
|
certFile = mkDefault cert;
|
||||||
|
|
|
@ -45,28 +45,12 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
config = let
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.kube-proxy = {
|
||||||
proxyPaths = filter (a: a != null) [
|
|
||||||
cfg.kubeconfig.caFile
|
|
||||||
cfg.kubeconfig.certFile
|
|
||||||
cfg.kubeconfig.keyFile
|
|
||||||
];
|
|
||||||
|
|
||||||
in mkIf cfg.enable {
|
|
||||||
systemd.services.kube-proxy = rec {
|
|
||||||
description = "Kubernetes Proxy Service";
|
description = "Kubernetes Proxy Service";
|
||||||
wantedBy = [ "kube-node-online.target" ];
|
wantedBy = [ "kubernetes.target" ];
|
||||||
after = [ "kubelet-online.service" ];
|
after = [ "kube-apiserver.service" ];
|
||||||
before = [ "kube-node-online.target" ];
|
path = with pkgs; [ iptables conntrack_tools ];
|
||||||
environment.KUBECONFIG = top.lib.mkKubeConfig "kube-proxy" cfg.kubeconfig;
|
|
||||||
path = with pkgs; [ iptables conntrack_tools kubectl ];
|
|
||||||
preStart = ''
|
|
||||||
until kubectl auth can-i get nodes/${top.kubelet.hostname} -q 2>/dev/null; do
|
|
||||||
echo kubectl auth can-i get nodes/${top.kubelet.hostname}: exit status $?
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Slice = "kubernetes.slice";
|
Slice = "kubernetes.slice";
|
||||||
ExecStart = ''${top.package}/bin/kube-proxy \
|
ExecStart = ''${top.package}/bin/kube-proxy \
|
||||||
|
@ -75,7 +59,7 @@ in
|
||||||
"--cluster-cidr=${top.clusterCidr}"} \
|
"--cluster-cidr=${top.clusterCidr}"} \
|
||||||
${optionalString (cfg.featureGates != [])
|
${optionalString (cfg.featureGates != [])
|
||||||
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
||||||
--kubeconfig=${environment.KUBECONFIG} \
|
--kubeconfig=${top.lib.mkKubeConfig "kube-proxy" cfg.kubeconfig} \
|
||||||
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
|
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
|
||||||
${cfg.extraOpts}
|
${cfg.extraOpts}
|
||||||
'';
|
'';
|
||||||
|
@ -83,15 +67,6 @@ in
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 5;
|
RestartSec = 5;
|
||||||
};
|
};
|
||||||
unitConfig.ConditionPathExists = proxyPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.kube-proxy = {
|
|
||||||
wantedBy = [ "kube-proxy.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = proxyPaths;
|
|
||||||
PathChanged = proxyPaths;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.kubernetes.pki.certs = {
|
services.kubernetes.pki.certs = {
|
||||||
|
|
|
@ -56,35 +56,18 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
config = let
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.kube-scheduler = {
|
||||||
schedulerPaths = filter (a: a != null) [
|
|
||||||
cfg.kubeconfig.caFile
|
|
||||||
cfg.kubeconfig.certFile
|
|
||||||
cfg.kubeconfig.keyFile
|
|
||||||
];
|
|
||||||
|
|
||||||
in mkIf cfg.enable {
|
|
||||||
systemd.services.kube-scheduler = rec {
|
|
||||||
description = "Kubernetes Scheduler Service";
|
description = "Kubernetes Scheduler Service";
|
||||||
wantedBy = [ "kube-control-plane-online.target" ];
|
wantedBy = [ "kubernetes.target" ];
|
||||||
after = [ "kube-apiserver.service" ];
|
after = [ "kube-apiserver.service" ];
|
||||||
before = [ "kube-control-plane-online.target" ];
|
|
||||||
environment.KUBECONFIG = top.lib.mkKubeConfig "kube-scheduler" cfg.kubeconfig;
|
|
||||||
path = [ pkgs.kubectl ];
|
|
||||||
preStart = ''
|
|
||||||
until kubectl auth can-i get /api -q 2>/dev/null; do
|
|
||||||
echo kubectl auth can-i get /api: exit status $?
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Slice = "kubernetes.slice";
|
Slice = "kubernetes.slice";
|
||||||
ExecStart = ''${top.package}/bin/kube-scheduler \
|
ExecStart = ''${top.package}/bin/kube-scheduler \
|
||||||
--address=${cfg.address} \
|
--address=${cfg.address} \
|
||||||
${optionalString (cfg.featureGates != [])
|
${optionalString (cfg.featureGates != [])
|
||||||
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
||||||
--kubeconfig=${environment.KUBECONFIG} \
|
--kubeconfig=${top.lib.mkKubeConfig "kube-scheduler" cfg.kubeconfig} \
|
||||||
--leader-elect=${boolToString cfg.leaderElect} \
|
--leader-elect=${boolToString cfg.leaderElect} \
|
||||||
--port=${toString cfg.port} \
|
--port=${toString cfg.port} \
|
||||||
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
|
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
|
||||||
|
@ -96,15 +79,6 @@ in
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 5;
|
RestartSec = 5;
|
||||||
};
|
};
|
||||||
unitConfig.ConditionPathExists = schedulerPaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.kube-scheduler = {
|
|
||||||
wantedBy = [ "kube-scheduler.service" ];
|
|
||||||
pathConfig = {
|
|
||||||
PathExists = schedulerPaths;
|
|
||||||
PathChanged = schedulerPaths;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.kubernetes.pki.certs = {
|
services.kubernetes.pki.certs = {
|
||||||
|
|
|
@ -81,6 +81,10 @@ in
|
||||||
default = "";
|
default = "";
|
||||||
description = ''
|
description = ''
|
||||||
Defines the mapping from system users to database users.
|
Defines the mapping from system users to database users.
|
||||||
|
|
||||||
|
The general form is:
|
||||||
|
|
||||||
|
map-name system-username database-username
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<para>
|
<para>
|
||||||
The latest stable version of Emacs 25 using the
|
The latest stable version of Emacs 25 using the
|
||||||
<link
|
<link
|
||||||
xlink:href="http://www.gtk.org">GTK+ 2</link>
|
xlink:href="http://www.gtk.org">GTK 2</link>
|
||||||
widget toolkit.
|
widget toolkit.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
@ -321,7 +321,7 @@ https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides
|
||||||
<para>
|
<para>
|
||||||
If you want, you can tweak the Emacs package itself from your
|
If you want, you can tweak the Emacs package itself from your
|
||||||
<filename>emacs.nix</filename>. For example, if you want to have a
|
<filename>emacs.nix</filename>. For example, if you want to have a
|
||||||
GTK+3-based Emacs instead of the default GTK+2-based binary and remove the
|
GTK 3-based Emacs instead of the default GTK 2-based binary and remove the
|
||||||
automatically generated <filename>emacs.desktop</filename> (useful is you
|
automatically generated <filename>emacs.desktop</filename> (useful is you
|
||||||
only use <command>emacsclient</command>), you can change your file
|
only use <command>emacsclient</command>), you can change your file
|
||||||
<filename>emacs.nix</filename> in this way:
|
<filename>emacs.nix</filename> in this way:
|
||||||
|
|
|
@ -121,6 +121,7 @@ in {
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d '${cfg.dataDir}' 0700 zookeeper - - -"
|
"d '${cfg.dataDir}' 0700 zookeeper - - -"
|
||||||
|
"Z '${cfg.dataDir}' 0700 zookeeper - - -"
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.zookeeper = {
|
systemd.services.zookeeper = {
|
||||||
|
|
|
@ -3,18 +3,18 @@
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
ceph = pkgs.ceph;
|
|
||||||
cfg = config.services.ceph;
|
cfg = config.services.ceph;
|
||||||
|
|
||||||
# function that translates "camelCaseOptions" to "camel case options", credits to tilpner in #nixos@freenode
|
# function that translates "camelCaseOptions" to "camel case options", credits to tilpner in #nixos@freenode
|
||||||
translateOption = replaceStrings upperChars (map (s: " ${s}") lowerChars);
|
expandCamelCase = replaceStrings upperChars (map (s: " ${s}") lowerChars);
|
||||||
generateDaemonList = (daemonType: daemons: extraServiceConfig:
|
expandCamelCaseAttrs = mapAttrs' (name: value: nameValuePair (expandCamelCase name) value);
|
||||||
mkMerge (
|
|
||||||
map (daemon:
|
makeServices = (daemonType: daemonIds: extraServiceConfig:
|
||||||
{ "ceph-${daemonType}-${daemon}" = generateServiceFile daemonType daemon cfg.global.clusterName ceph extraServiceConfig; }
|
mkMerge (map (daemonId:
|
||||||
) daemons
|
{ "ceph-${daemonType}-${daemonId}" = makeService daemonType daemonId cfg.global.clusterName pkgs.ceph extraServiceConfig; })
|
||||||
)
|
daemonIds));
|
||||||
);
|
|
||||||
generateServiceFile = (daemonType: daemonId: clusterName: ceph: extraServiceConfig: {
|
makeService = (daemonType: daemonId: clusterName: ceph: extraServiceConfig: {
|
||||||
enable = true;
|
enable = true;
|
||||||
description = "Ceph ${builtins.replaceStrings lowerChars upperChars daemonType} daemon ${daemonId}";
|
description = "Ceph ${builtins.replaceStrings lowerChars upperChars daemonType} daemon ${daemonId}";
|
||||||
after = [ "network-online.target" "time-sync.target" ] ++ optional (daemonType == "osd") "ceph-mon.target";
|
after = [ "network-online.target" "time-sync.target" ] ++ optional (daemonType == "osd") "ceph-mon.target";
|
||||||
|
@ -34,23 +34,29 @@ let
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
StartLimitBurst = "5";
|
StartLimitBurst = "5";
|
||||||
StartLimitInterval = "30min";
|
StartLimitInterval = "30min";
|
||||||
ExecStart = "${ceph.out}/bin/${if daemonType == "rgw" then "radosgw" else "ceph-${daemonType}"} -f --cluster ${clusterName} --id ${if daemonType == "rgw" then "client.${daemonId}" else daemonId} --setuser ceph --setgroup ceph";
|
ExecStart = ''${ceph.out}/bin/${if daemonType == "rgw" then "radosgw" else "ceph-${daemonType}"} \
|
||||||
|
-f --cluster ${clusterName} --id ${daemonId} --setuser ceph \
|
||||||
|
--setgroup ${if daemonType == "osd" then "disk" else "ceph"}'';
|
||||||
} // extraServiceConfig
|
} // extraServiceConfig
|
||||||
// optionalAttrs (daemonType == "osd") { ExecStartPre = "${ceph.out}/libexec/ceph/ceph-osd-prestart.sh --id ${daemonId} --cluster ${clusterName}"; };
|
// optionalAttrs (daemonType == "osd") { ExecStartPre = ''${ceph.lib}/libexec/ceph/ceph-osd-prestart.sh \
|
||||||
} // optionalAttrs (builtins.elem daemonType [ "mds" "mon" "rgw" "mgr" ]) { preStart = ''
|
--id ${daemonId} --cluster ${clusterName}''; };
|
||||||
|
} // optionalAttrs (builtins.elem daemonType [ "mds" "mon" "rgw" "mgr" ]) {
|
||||||
|
preStart = ''
|
||||||
daemonPath="/var/lib/ceph/${if daemonType == "rgw" then "radosgw" else daemonType}/${clusterName}-${daemonId}"
|
daemonPath="/var/lib/ceph/${if daemonType == "rgw" then "radosgw" else daemonType}/${clusterName}-${daemonId}"
|
||||||
if [ ! -d ''$daemonPath ]; then
|
if [ ! -d $daemonPath ]; then
|
||||||
mkdir -m 755 -p ''$daemonPath
|
mkdir -m 755 -p $daemonPath
|
||||||
chown -R ceph:ceph ''$daemonPath
|
chown -R ceph:ceph $daemonPath
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
} // optionalAttrs (daemonType == "osd") { path = [ pkgs.getopt ]; }
|
} // optionalAttrs (daemonType == "osd") { path = [ pkgs.getopt ]; }
|
||||||
);
|
);
|
||||||
generateTargetFile = (daemonType:
|
|
||||||
|
makeTarget = (daemonType:
|
||||||
{
|
{
|
||||||
"ceph-${daemonType}" = {
|
"ceph-${daemonType}" = {
|
||||||
description = "Ceph target allowing to start/stop all ceph-${daemonType} services at once";
|
description = "Ceph target allowing to start/stop all ceph-${daemonType} services at once";
|
||||||
partOf = [ "ceph.target" ];
|
partOf = [ "ceph.target" ];
|
||||||
|
wantedBy = [ "ceph.target" ];
|
||||||
before = [ "ceph.target" ];
|
before = [ "ceph.target" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -82,6 +88,14 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mgrModulePath = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "${pkgs.ceph.lib}/lib/ceph/mgr";
|
||||||
|
description = ''
|
||||||
|
Path at which to find ceph-mgr modules.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
monInitialMembers = mkOption {
|
monInitialMembers = mkOption {
|
||||||
type = with types; nullOr commas;
|
type = with types; nullOr commas;
|
||||||
default = null;
|
default = null;
|
||||||
|
@ -157,6 +171,27 @@ in
|
||||||
A comma-separated list of subnets that will be used as cluster networks in the cluster.
|
A comma-separated list of subnets that will be used as cluster networks in the cluster.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rgwMimeTypesFile = mkOption {
|
||||||
|
type = with types; nullOr path;
|
||||||
|
default = "${pkgs.mime-types}/etc/mime.types";
|
||||||
|
description = ''
|
||||||
|
Path to mime types used by radosgw.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = with types; attrsOf str;
|
||||||
|
default = {};
|
||||||
|
example = ''
|
||||||
|
{
|
||||||
|
"ms bind ipv6" = "true";
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Extra configuration to add to the global section. Use for setting values that are common for all daemons in the cluster.
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
mgr = {
|
mgr = {
|
||||||
|
@ -216,6 +251,7 @@ in
|
||||||
to the id part in ceph i.e. [ "name1" ] would result in osd.name1
|
to the id part in ceph i.e. [ "name1" ] would result in osd.name1
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = with types; attrsOf str;
|
type = with types; attrsOf str;
|
||||||
default = {
|
default = {
|
||||||
|
@ -296,9 +332,6 @@ in
|
||||||
{ assertion = cfg.global.fsid != "";
|
{ assertion = cfg.global.fsid != "";
|
||||||
message = "fsid has to be set to a valid uuid for the cluster to function";
|
message = "fsid has to be set to a valid uuid for the cluster to function";
|
||||||
}
|
}
|
||||||
{ assertion = cfg.mgr.enable == true;
|
|
||||||
message = "ceph 12.x requires atleast 1 MGR daemon enabled for the cluster to function";
|
|
||||||
}
|
|
||||||
{ assertion = cfg.mon.enable == true -> cfg.mon.daemons != [];
|
{ assertion = cfg.mon.enable == true -> cfg.mon.daemons != [];
|
||||||
message = "have to set id of atleast one MON if you're going to enable Monitor";
|
message = "have to set id of atleast one MON if you're going to enable Monitor";
|
||||||
}
|
}
|
||||||
|
@ -317,14 +350,12 @@ in
|
||||||
''Not setting up a list of members in monInitialMembers requires that you set the host variable for each mon daemon or else the cluster won't function'';
|
''Not setting up a list of members in monInitialMembers requires that you set the host variable for each mon daemon or else the cluster won't function'';
|
||||||
|
|
||||||
environment.etc."ceph/ceph.conf".text = let
|
environment.etc."ceph/ceph.conf".text = let
|
||||||
# Translate camelCaseOptions to the expected camel case option for ceph.conf
|
|
||||||
translatedGlobalConfig = mapAttrs' (name: value: nameValuePair (translateOption name) value) cfg.global;
|
|
||||||
# Merge the extraConfig set for mgr daemons, as mgr don't have their own section
|
# Merge the extraConfig set for mgr daemons, as mgr don't have their own section
|
||||||
globalAndMgrConfig = translatedGlobalConfig // optionalAttrs cfg.mgr.enable cfg.mgr.extraConfig;
|
globalSection = expandCamelCaseAttrs (cfg.global // cfg.extraConfig // optionalAttrs cfg.mgr.enable cfg.mgr.extraConfig);
|
||||||
# Remove all name-value pairs with null values from the attribute set to avoid making empty sections in the ceph.conf
|
# Remove all name-value pairs with null values from the attribute set to avoid making empty sections in the ceph.conf
|
||||||
globalConfig = mapAttrs' (name: value: nameValuePair (translateOption name) value) (filterAttrs (name: value: value != null) globalAndMgrConfig);
|
globalSection' = filterAttrs (name: value: value != null) globalSection;
|
||||||
totalConfig = {
|
totalConfig = {
|
||||||
global = globalConfig;
|
global = globalSection';
|
||||||
} // optionalAttrs (cfg.mon.enable && cfg.mon.extraConfig != {}) { mon = cfg.mon.extraConfig; }
|
} // optionalAttrs (cfg.mon.enable && cfg.mon.extraConfig != {}) { mon = cfg.mon.extraConfig; }
|
||||||
// optionalAttrs (cfg.mds.enable && cfg.mds.extraConfig != {}) { mds = cfg.mds.extraConfig; }
|
// optionalAttrs (cfg.mds.enable && cfg.mds.extraConfig != {}) { mds = cfg.mds.extraConfig; }
|
||||||
// optionalAttrs (cfg.osd.enable && cfg.osd.extraConfig != {}) { osd = cfg.osd.extraConfig; }
|
// optionalAttrs (cfg.osd.enable && cfg.osd.extraConfig != {}) { osd = cfg.osd.extraConfig; }
|
||||||
|
@ -336,8 +367,9 @@ in
|
||||||
name = "ceph";
|
name = "ceph";
|
||||||
uid = config.ids.uids.ceph;
|
uid = config.ids.uids.ceph;
|
||||||
description = "Ceph daemon user";
|
description = "Ceph daemon user";
|
||||||
|
group = "ceph";
|
||||||
|
extraGroups = [ "disk" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups = singleton {
|
users.groups = singleton {
|
||||||
name = "ceph";
|
name = "ceph";
|
||||||
gid = config.ids.gids.ceph;
|
gid = config.ids.gids.ceph;
|
||||||
|
@ -345,22 +377,26 @@ in
|
||||||
|
|
||||||
systemd.services = let
|
systemd.services = let
|
||||||
services = []
|
services = []
|
||||||
++ optional cfg.mon.enable (generateDaemonList "mon" cfg.mon.daemons { RestartSec = "10"; })
|
++ optional cfg.mon.enable (makeServices "mon" cfg.mon.daemons { RestartSec = "10"; })
|
||||||
++ optional cfg.mds.enable (generateDaemonList "mds" cfg.mds.daemons { StartLimitBurst = "3"; })
|
++ optional cfg.mds.enable (makeServices "mds" cfg.mds.daemons { StartLimitBurst = "3"; })
|
||||||
++ optional cfg.osd.enable (generateDaemonList "osd" cfg.osd.daemons { StartLimitBurst = "30"; RestartSec = "20s"; })
|
++ optional cfg.osd.enable (makeServices "osd" cfg.osd.daemons { StartLimitBurst = "30";
|
||||||
++ optional cfg.rgw.enable (generateDaemonList "rgw" cfg.rgw.daemons { })
|
RestartSec = "20s";
|
||||||
++ optional cfg.mgr.enable (generateDaemonList "mgr" cfg.mgr.daemons { StartLimitBurst = "3"; });
|
PrivateDevices = "no"; # osd needs disk access
|
||||||
|
})
|
||||||
|
++ optional cfg.rgw.enable (makeServices "rgw" cfg.rgw.daemons { })
|
||||||
|
++ optional cfg.mgr.enable (makeServices "mgr" cfg.mgr.daemons { StartLimitBurst = "3"; });
|
||||||
in
|
in
|
||||||
mkMerge services;
|
mkMerge services;
|
||||||
|
|
||||||
systemd.targets = let
|
systemd.targets = let
|
||||||
targets = [
|
targets = [
|
||||||
{ ceph = { description = "Ceph target allowing to start/stop all ceph service instances at once"; }; }
|
{ "ceph" = { description = "Ceph target allowing to start/stop all ceph service instances at once";
|
||||||
] ++ optional cfg.mon.enable (generateTargetFile "mon")
|
wantedBy = [ "multi-user.target" ]; }; }
|
||||||
++ optional cfg.mds.enable (generateTargetFile "mds")
|
] ++ optional cfg.mon.enable (makeTarget "mon")
|
||||||
++ optional cfg.osd.enable (generateTargetFile "osd")
|
++ optional cfg.mds.enable (makeTarget "mds")
|
||||||
++ optional cfg.rgw.enable (generateTargetFile "rgw")
|
++ optional cfg.osd.enable (makeTarget "osd")
|
||||||
++ optional cfg.mgr.enable (generateTargetFile "mgr");
|
++ optional cfg.rgw.enable (makeTarget "rgw")
|
||||||
|
++ optional cfg.mgr.enable (makeTarget "mgr");
|
||||||
in
|
in
|
||||||
mkMerge targets;
|
mkMerge targets;
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ in {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
ExecStart = "${cfg.package}/bin/darkhttpd ${args}";
|
ExecStart = "${pkgs.darkhttpd}/bin/darkhttpd ${args}";
|
||||||
AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
|
AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "2s";
|
RestartSec = "2s";
|
||||||
|
|
|
@ -31,7 +31,7 @@ in
|
||||||
e.efl e.enlightenment
|
e.efl e.enlightenment
|
||||||
e.terminology e.econnman
|
e.terminology e.econnman
|
||||||
pkgs.xorg.xauth # used by kdesu
|
pkgs.xorg.xauth # used by kdesu
|
||||||
pkgs.gtk2 # To get GTK+'s themes.
|
pkgs.gtk2 # To get GTK's themes.
|
||||||
pkgs.tango-icon-theme
|
pkgs.tango-icon-theme
|
||||||
|
|
||||||
pkgs.gnome2.gnome_icon_theme
|
pkgs.gnome2.gnome_icon_theme
|
||||||
|
@ -48,7 +48,7 @@ in
|
||||||
services.xserver.desktopManager.session = [
|
services.xserver.desktopManager.session = [
|
||||||
{ name = "Enlightenment";
|
{ name = "Enlightenment";
|
||||||
start = ''
|
start = ''
|
||||||
# Set GTK_DATA_PREFIX so that GTK+ can find the themes
|
# Set GTK_DATA_PREFIX so that GTK can find the themes
|
||||||
export GTK_DATA_PREFIX=${config.system.path}
|
export GTK_DATA_PREFIX=${config.system.path}
|
||||||
# find theme engines
|
# find theme engines
|
||||||
export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0
|
export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0
|
||||||
|
|
|
@ -48,7 +48,7 @@ in
|
||||||
name = "mate";
|
name = "mate";
|
||||||
bgSupport = true;
|
bgSupport = true;
|
||||||
start = ''
|
start = ''
|
||||||
# Set GTK_DATA_PREFIX so that GTK+ can find the themes
|
# Set GTK_DATA_PREFIX so that GTK can find the themes
|
||||||
export GTK_DATA_PREFIX=${config.system.path}
|
export GTK_DATA_PREFIX=${config.system.path}
|
||||||
|
|
||||||
# Find theme engines
|
# Find theme engines
|
||||||
|
|
|
@ -48,7 +48,7 @@ in
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = with pkgs.xfce // pkgs; [
|
environment.systemPackages = with pkgs.xfce // pkgs; [
|
||||||
# Get GTK+ themes and gtk-update-icon-cache
|
# Get GTK themes and gtk-update-icon-cache
|
||||||
gtk2.out
|
gtk2.out
|
||||||
|
|
||||||
# Supplies some abstract icons such as:
|
# Supplies some abstract icons such as:
|
||||||
|
@ -107,10 +107,10 @@ in
|
||||||
start = ''
|
start = ''
|
||||||
${cfg.extraSessionCommands}
|
${cfg.extraSessionCommands}
|
||||||
|
|
||||||
# Set GTK_PATH so that GTK+ can find the theme engines.
|
# Set GTK_PATH so that GTK can find the theme engines.
|
||||||
export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"
|
export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"
|
||||||
|
|
||||||
# Set GTK_DATA_PREFIX so that GTK+ can find the Xfce themes.
|
# Set GTK_DATA_PREFIX so that GTK can find the Xfce themes.
|
||||||
export GTK_DATA_PREFIX=${config.system.path}
|
export GTK_DATA_PREFIX=${config.system.path}
|
||||||
|
|
||||||
${pkgs.runtimeShell} ${pkgs.xfce.xinitrc} &
|
${pkgs.runtimeShell} ${pkgs.xfce.xinitrc} &
|
||||||
|
|
|
@ -114,10 +114,10 @@ in
|
||||||
name = "xfce4-14";
|
name = "xfce4-14";
|
||||||
bgSupport = true;
|
bgSupport = true;
|
||||||
start = ''
|
start = ''
|
||||||
# Set GTK_PATH so that GTK+ can find the theme engines.
|
# Set GTK_PATH so that GTK can find the theme engines.
|
||||||
export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"
|
export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"
|
||||||
|
|
||||||
# Set GTK_DATA_PREFIX so that GTK+ can find the Xfce themes.
|
# Set GTK_DATA_PREFIX so that GTK can find the Xfce themes.
|
||||||
export GTK_DATA_PREFIX=${config.system.path}
|
export GTK_DATA_PREFIX=${config.system.path}
|
||||||
|
|
||||||
${pkgs.runtimeShell} ${pkgs.xfce4-14.xinitrc} &
|
${pkgs.runtimeShell} ${pkgs.xfce4-14.xinitrc} &
|
||||||
|
|
|
@ -25,6 +25,9 @@ in
|
||||||
{ assertion = cfg.hvm;
|
{ assertion = cfg.hvm;
|
||||||
message = "Paravirtualized EC2 instances are no longer supported.";
|
message = "Paravirtualized EC2 instances are no longer supported.";
|
||||||
}
|
}
|
||||||
|
{ assertion = cfg.efi -> cfg.hvm;
|
||||||
|
message = "EC2 instances using EFI must be HVM instances.";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.growPartition = cfg.hvm;
|
boot.growPartition = cfg.hvm;
|
||||||
|
@ -35,6 +38,11 @@ in
|
||||||
autoResize = true;
|
autoResize = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fileSystems."/boot" = mkIf cfg.efi {
|
||||||
|
device = "/dev/disk/by-label/ESP";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
|
||||||
boot.extraModulePackages = [
|
boot.extraModulePackages = [
|
||||||
config.boot.kernelPackages.ena
|
config.boot.kernelPackages.ena
|
||||||
];
|
];
|
||||||
|
@ -50,8 +58,10 @@ in
|
||||||
|
|
||||||
# Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd.
|
# Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd.
|
||||||
boot.loader.grub.version = if cfg.hvm then 2 else 1;
|
boot.loader.grub.version = if cfg.hvm then 2 else 1;
|
||||||
boot.loader.grub.device = if cfg.hvm then "/dev/xvda" else "nodev";
|
boot.loader.grub.device = if (cfg.hvm && !cfg.efi) then "/dev/xvda" else "nodev";
|
||||||
boot.loader.grub.extraPerEntryConfig = mkIf (!cfg.hvm) "root (hd0)";
|
boot.loader.grub.extraPerEntryConfig = mkIf (!cfg.hvm) "root (hd0)";
|
||||||
|
boot.loader.grub.efiSupport = cfg.efi;
|
||||||
|
boot.loader.grub.efiInstallAsRemovable = cfg.efi;
|
||||||
boot.loader.timeout = 0;
|
boot.loader.timeout = 0;
|
||||||
|
|
||||||
boot.initrd.network.enable = true;
|
boot.initrd.network.enable = true;
|
||||||
|
@ -137,7 +147,7 @@ in
|
||||||
networking.timeServers = [ "169.254.169.123" ];
|
networking.timeServers = [ "169.254.169.123" ];
|
||||||
|
|
||||||
# udisks has become too bloated to have in a headless system
|
# udisks has become too bloated to have in a headless system
|
||||||
# (e.g. it depends on GTK+).
|
# (e.g. it depends on GTK).
|
||||||
services.udisks2.enable = false;
|
services.udisks2.enable = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
ec2 = {
|
ec2 = {
|
||||||
|
@ -9,6 +9,13 @@
|
||||||
Whether the EC2 instance is a HVM instance.
|
Whether the EC2 instance is a HVM instance.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
efi = lib.mkOption {
|
||||||
|
default = pkgs.stdenv.hostPlatform.isAarch64;
|
||||||
|
internal = true;
|
||||||
|
description = ''
|
||||||
|
Whether the EC2 instance is using EFI.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.railcar;
|
||||||
|
generateUnit = name: containerConfig:
|
||||||
|
let
|
||||||
|
container = pkgs.ociTools.buildContainer {
|
||||||
|
args = [
|
||||||
|
(pkgs.writeShellScript "run.sh" containerConfig.cmd).outPath
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
nameValuePair "railcar-${name}" {
|
||||||
|
enable = true;
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = ''
|
||||||
|
${cfg.package}/bin/railcar -r ${cfg.stateDir} run ${name} -b ${container}
|
||||||
|
'';
|
||||||
|
Type = containerConfig.runType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
mount = with types; (submodule {
|
||||||
|
options = {
|
||||||
|
type = mkOption {
|
||||||
|
type = string;
|
||||||
|
default = "none";
|
||||||
|
description = ''
|
||||||
|
The type of the filesystem to be mounted.
|
||||||
|
Linux: filesystem types supported by the kernel as listed in
|
||||||
|
`/proc/filesystems` (e.g., "minix", "ext2", "ext3", "jfs", "xfs",
|
||||||
|
"reiserfs", "msdos", "proc", "nfs", "iso9660"). For bind mounts
|
||||||
|
(when options include either bind or rbind), the type is a dummy,
|
||||||
|
often "none" (not listed in /proc/filesystems).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
source = mkOption {
|
||||||
|
type = string;
|
||||||
|
description = "Source for the in-container mount";
|
||||||
|
};
|
||||||
|
options = mkOption {
|
||||||
|
type = loaOf (string);
|
||||||
|
default = [ "bind" ];
|
||||||
|
description = ''
|
||||||
|
Mount options of the filesystem to be used.
|
||||||
|
|
||||||
|
Support optoions are listed in the mount(8) man page. Note that
|
||||||
|
both filesystem-independent and filesystem-specific options
|
||||||
|
are listed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.railcar = {
|
||||||
|
enable = mkEnableOption "railcar";
|
||||||
|
|
||||||
|
containers = mkOption {
|
||||||
|
default = {};
|
||||||
|
description = "Declarative container configuration";
|
||||||
|
type = with types; loaOf (submodule ({ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
cmd = mkOption {
|
||||||
|
type = types.string;
|
||||||
|
description = "Command or script to run inside the container";
|
||||||
|
};
|
||||||
|
|
||||||
|
mounts = mkOption {
|
||||||
|
type = with types; attrsOf mount;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
A set of mounts inside the container.
|
||||||
|
|
||||||
|
The defaults have been chosen for simple bindmounts, meaning
|
||||||
|
that you only need to provide the "source" parameter.
|
||||||
|
'';
|
||||||
|
example = ''
|
||||||
|
{ "/data" = { source = "/var/lib/data"; }; }
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
runType = mkOption {
|
||||||
|
type = types.string;
|
||||||
|
default = "oneshot";
|
||||||
|
description = "The systemd service run type";
|
||||||
|
};
|
||||||
|
|
||||||
|
os = mkOption {
|
||||||
|
type = types.string;
|
||||||
|
default = "linux";
|
||||||
|
description = "OS type of the container";
|
||||||
|
};
|
||||||
|
|
||||||
|
arch = mkOption {
|
||||||
|
type = types.string;
|
||||||
|
default = "x86_64";
|
||||||
|
description = "Computer architecture type of the container";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
stateDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = ''/var/railcar'';
|
||||||
|
description = "Railcar persistent state directory";
|
||||||
|
};
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.railcar;
|
||||||
|
description = "Railcar package to use";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services = flip mapAttrs' cfg.containers (name: containerConfig:
|
||||||
|
generateUnit name containerConfig
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -196,6 +196,22 @@ in rec {
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
# A disk image that can be imported to Amazon EC2 and registered as an AMI
|
||||||
|
amazonImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
|
||||||
|
|
||||||
|
with import nixpkgs { inherit system; };
|
||||||
|
|
||||||
|
hydraJob ((import lib/eval-config.nix {
|
||||||
|
inherit system;
|
||||||
|
modules =
|
||||||
|
[ versionModule
|
||||||
|
./maintainers/scripts/ec2/amazon-image.nix
|
||||||
|
];
|
||||||
|
}).config.system.build.amazonImage)
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
# Ensure that all packages used by the minimal NixOS config end up in the channel.
|
# Ensure that all packages used by the minimal NixOS config end up in the channel.
|
||||||
dummy = forAllSystems (system: pkgs.runCommand "dummy"
|
dummy = forAllSystems (system: pkgs.runCommand "dummy"
|
||||||
{ toplevel = (import lib/eval-config.nix {
|
{ toplevel = (import lib/eval-config.nix {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ./make-test.nix ({pkgs, ...}: {
|
import ./make-test.nix ({pkgs, lib, ...}: {
|
||||||
name = "All-in-one-basic-ceph-cluster";
|
name = "All-in-one-basic-ceph-cluster";
|
||||||
meta = with pkgs.stdenv.lib.maintainers; {
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
maintainers = [ lejonet ];
|
maintainers = [ lejonet ];
|
||||||
|
@ -7,6 +7,7 @@ import ./make-test.nix ({pkgs, ...}: {
|
||||||
nodes = {
|
nodes = {
|
||||||
aio = { pkgs, ... }: {
|
aio = { pkgs, ... }: {
|
||||||
virtualisation = {
|
virtualisation = {
|
||||||
|
memorySize = 1536;
|
||||||
emptyDiskImages = [ 20480 20480 ];
|
emptyDiskImages = [ 20480 20480 ];
|
||||||
vlans = [ 1 ];
|
vlans = [ 1 ];
|
||||||
};
|
};
|
||||||
|
@ -24,9 +25,6 @@ import ./make-test.nix ({pkgs, ...}: {
|
||||||
ceph
|
ceph
|
||||||
xfsprogs
|
xfsprogs
|
||||||
];
|
];
|
||||||
nixpkgs.config.packageOverrides = super: {
|
|
||||||
ceph = super.ceph.override({ nss = super.nss; libxfs = super.libxfs; libaio = super.libaio; jemalloc = super.jemalloc; });
|
|
||||||
};
|
|
||||||
|
|
||||||
boot.kernelModules = [ "xfs" ];
|
boot.kernelModules = [ "xfs" ];
|
||||||
|
|
||||||
|
@ -51,6 +49,9 @@ import ./make-test.nix ({pkgs, ...}: {
|
||||||
enable = true;
|
enable = true;
|
||||||
daemons = [ "0" "1" ];
|
daemons = [ "0" "1" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# So that we don't have to battle systemd when bootstraping
|
||||||
|
systemd.targets.ceph.wantedBy = lib.mkForce [];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,24 +62,26 @@ import ./make-test.nix ({pkgs, ...}: {
|
||||||
|
|
||||||
# Create the ceph-related directories
|
# Create the ceph-related directories
|
||||||
$aio->mustSucceed(
|
$aio->mustSucceed(
|
||||||
"mkdir -p /var/lib/ceph/mgr/ceph-aio/",
|
"mkdir -p /var/lib/ceph/mgr/ceph-aio",
|
||||||
"mkdir -p /var/lib/ceph/mon/ceph-aio/",
|
"mkdir -p /var/lib/ceph/mon/ceph-aio",
|
||||||
"mkdir -p /var/lib/ceph/osd/ceph-{0..1}/",
|
"mkdir -p /var/lib/ceph/osd/ceph-{0,1}",
|
||||||
"chown ceph:ceph -R /var/lib/ceph/"
|
"chown ceph:ceph -R /var/lib/ceph/",
|
||||||
|
"mkdir -p /etc/ceph",
|
||||||
|
"chown ceph:ceph -R /etc/ceph"
|
||||||
);
|
);
|
||||||
|
|
||||||
# Bootstrap ceph-mon daemon
|
# Bootstrap ceph-mon daemon
|
||||||
$aio->mustSucceed(
|
$aio->mustSucceed(
|
||||||
"mkdir -p /var/lib/ceph/bootstrap-osd && chown ceph:ceph /var/lib/ceph/bootstrap-osd",
|
|
||||||
"sudo -u ceph ceph-authtool --create-keyring /tmp/ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *'",
|
"sudo -u ceph ceph-authtool --create-keyring /tmp/ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *'",
|
||||||
"ceph-authtool --create-keyring /etc/ceph/ceph.client.admin.keyring --gen-key -n client.admin --set-uid=0 --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'",
|
"sudo -u ceph ceph-authtool --create-keyring /etc/ceph/ceph.client.admin.keyring --gen-key -n client.admin --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'",
|
||||||
"ceph-authtool /tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring",
|
"sudo -u ceph ceph-authtool /tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring",
|
||||||
"monmaptool --create --add aio 192.168.1.1 --fsid 066ae264-2a5d-4729-8001-6ad265f50b03 /tmp/monmap",
|
"monmaptool --create --add aio 192.168.1.1 --fsid 066ae264-2a5d-4729-8001-6ad265f50b03 /tmp/monmap",
|
||||||
"sudo -u ceph ceph-mon --mkfs -i aio --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring",
|
"sudo -u ceph ceph-mon --mkfs -i aio --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring",
|
||||||
"touch /var/lib/ceph/mon/ceph-aio/done",
|
"sudo -u ceph touch /var/lib/ceph/mon/ceph-aio/done",
|
||||||
"systemctl start ceph-mon-aio"
|
"systemctl start ceph-mon-aio"
|
||||||
);
|
);
|
||||||
$aio->waitForUnit("ceph-mon-aio");
|
$aio->waitForUnit("ceph-mon-aio");
|
||||||
|
$aio->mustSucceed("ceph mon enable-msgr2");
|
||||||
|
|
||||||
# Can't check ceph status until a mon is up
|
# Can't check ceph status until a mon is up
|
||||||
$aio->succeed("ceph -s | grep 'mon: 1 daemons'");
|
$aio->succeed("ceph -s | grep 'mon: 1 daemons'");
|
||||||
|
@ -90,6 +93,7 @@ import ./make-test.nix ({pkgs, ...}: {
|
||||||
);
|
);
|
||||||
$aio->waitForUnit("ceph-mgr-aio");
|
$aio->waitForUnit("ceph-mgr-aio");
|
||||||
$aio->waitUntilSucceeds("ceph -s | grep 'quorum aio'");
|
$aio->waitUntilSucceeds("ceph -s | grep 'quorum aio'");
|
||||||
|
$aio->waitUntilSucceeds("ceph -s | grep 'mgr: aio(active,'");
|
||||||
|
|
||||||
# Bootstrap both OSDs
|
# Bootstrap both OSDs
|
||||||
$aio->mustSucceed(
|
$aio->mustSucceed(
|
||||||
|
@ -112,8 +116,8 @@ import ./make-test.nix ({pkgs, ...}: {
|
||||||
"systemctl start ceph-osd-1"
|
"systemctl start ceph-osd-1"
|
||||||
);
|
);
|
||||||
|
|
||||||
$aio->waitUntilSucceeds("ceph osd stat | grep '2 osds: 2 up, 2 in'");
|
$aio->waitUntilSucceeds("ceph osd stat | grep -e '2 osds: 2 up[^,]*, 2 in'");
|
||||||
$aio->waitUntilSucceeds("ceph -s | grep 'mgr: aio(active)'");
|
$aio->waitUntilSucceeds("ceph -s | grep 'mgr: aio(active,'");
|
||||||
$aio->waitUntilSucceeds("ceph -s | grep 'HEALTH_OK'");
|
$aio->waitUntilSucceeds("ceph -s | grep 'HEALTH_OK'");
|
||||||
|
|
||||||
$aio->mustSucceed(
|
$aio->mustSucceed(
|
||||||
|
@ -135,5 +139,23 @@ import ./make-test.nix ({pkgs, ...}: {
|
||||||
"ceph osd pool ls | grep 'aio-test'",
|
"ceph osd pool ls | grep 'aio-test'",
|
||||||
"ceph osd pool delete aio-other-test aio-other-test --yes-i-really-really-mean-it"
|
"ceph osd pool delete aio-other-test aio-other-test --yes-i-really-really-mean-it"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# As we disable the target in the config, we still want to test that it works as intended
|
||||||
|
$aio->mustSucceed(
|
||||||
|
"systemctl stop ceph-osd-0",
|
||||||
|
"systemctl stop ceph-osd-1",
|
||||||
|
"systemctl stop ceph-mgr-aio",
|
||||||
|
"systemctl stop ceph-mon-aio"
|
||||||
|
);
|
||||||
|
$aio->succeed("systemctl start ceph.target");
|
||||||
|
$aio->waitForUnit("ceph-mon-aio");
|
||||||
|
$aio->waitForUnit("ceph-mgr-aio");
|
||||||
|
$aio->waitForUnit("ceph-osd-0");
|
||||||
|
$aio->waitForUnit("ceph-osd-1");
|
||||||
|
$aio->succeed("ceph -s | grep 'mon: 1 daemons'");
|
||||||
|
$aio->waitUntilSucceeds("ceph -s | grep 'quorum aio'");
|
||||||
|
$aio->waitUntilSucceeds("ceph osd stat | grep -e '2 osds: 2 up[^,]*, 2 in'");
|
||||||
|
$aio->waitUntilSucceeds("ceph -s | grep 'mgr: aio(active,'");
|
||||||
|
$aio->waitUntilSucceeds("ceph -s | grep 'HEALTH_OK'");
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
|
@ -30,10 +30,7 @@ let
|
||||||
{ config, pkgs, lib, nodes, ... }:
|
{ config, pkgs, lib, nodes, ... }:
|
||||||
mkMerge [
|
mkMerge [
|
||||||
{
|
{
|
||||||
boot = {
|
boot.postBootCommands = "rm -fr /var/lib/kubernetes/secrets /tmp/shared/*";
|
||||||
postBootCommands = "rm -fr /var/lib/kubernetes/secrets /tmp/shared/*";
|
|
||||||
kernel.sysctl = { "fs.inotify.max_user_instances" = 256; };
|
|
||||||
};
|
|
||||||
virtualisation.memorySize = mkDefault 1536;
|
virtualisation.memorySize = mkDefault 1536;
|
||||||
virtualisation.diskSize = mkDefault 4096;
|
virtualisation.diskSize = mkDefault 4096;
|
||||||
networking = {
|
networking = {
|
||||||
|
|
|
@ -77,7 +77,6 @@ let
|
||||||
singleNodeTest = {
|
singleNodeTest = {
|
||||||
test = ''
|
test = ''
|
||||||
# prepare machine1 for test
|
# prepare machine1 for test
|
||||||
$machine1->waitForUnit("kubernetes.target");
|
|
||||||
$machine1->waitUntilSucceeds("kubectl get node machine1.${domain} | grep -w Ready");
|
$machine1->waitUntilSucceeds("kubectl get node machine1.${domain} | grep -w Ready");
|
||||||
$machine1->waitUntilSucceeds("docker load < ${redisImage}");
|
$machine1->waitUntilSucceeds("docker load < ${redisImage}");
|
||||||
$machine1->waitUntilSucceeds("kubectl create -f ${redisPod}");
|
$machine1->waitUntilSucceeds("kubectl create -f ${redisPod}");
|
||||||
|
@ -103,8 +102,6 @@ let
|
||||||
# Node token exchange
|
# Node token exchange
|
||||||
$machine1->waitUntilSucceeds("cp -f /var/lib/cfssl/apitoken.secret /tmp/shared/apitoken.secret");
|
$machine1->waitUntilSucceeds("cp -f /var/lib/cfssl/apitoken.secret /tmp/shared/apitoken.secret");
|
||||||
$machine2->waitUntilSucceeds("cat /tmp/shared/apitoken.secret | nixos-kubernetes-node-join");
|
$machine2->waitUntilSucceeds("cat /tmp/shared/apitoken.secret | nixos-kubernetes-node-join");
|
||||||
$machine1->waitForUnit("kubernetes.target");
|
|
||||||
$machine2->waitForUnit("kubernetes.target");
|
|
||||||
|
|
||||||
# prepare machines for test
|
# prepare machines for test
|
||||||
$machine1->waitUntilSucceeds("kubectl get node machine2.${domain} | grep -w Ready");
|
$machine1->waitUntilSucceeds("kubectl get node machine2.${domain} | grep -w Ready");
|
||||||
|
|
|
@ -94,8 +94,6 @@ let
|
||||||
|
|
||||||
singlenode = base // {
|
singlenode = base // {
|
||||||
test = ''
|
test = ''
|
||||||
$machine1->waitForUnit("kubernetes.target");
|
|
||||||
|
|
||||||
$machine1->waitUntilSucceeds("kubectl get node machine1.my.zyx | grep -w Ready");
|
$machine1->waitUntilSucceeds("kubectl get node machine1.my.zyx | grep -w Ready");
|
||||||
|
|
||||||
$machine1->waitUntilSucceeds("docker load < ${kubectlImage}");
|
$machine1->waitUntilSucceeds("docker load < ${kubectlImage}");
|
||||||
|
@ -118,8 +116,6 @@ let
|
||||||
# Node token exchange
|
# Node token exchange
|
||||||
$machine1->waitUntilSucceeds("cp -f /var/lib/cfssl/apitoken.secret /tmp/shared/apitoken.secret");
|
$machine1->waitUntilSucceeds("cp -f /var/lib/cfssl/apitoken.secret /tmp/shared/apitoken.secret");
|
||||||
$machine2->waitUntilSucceeds("cat /tmp/shared/apitoken.secret | nixos-kubernetes-node-join");
|
$machine2->waitUntilSucceeds("cat /tmp/shared/apitoken.secret | nixos-kubernetes-node-join");
|
||||||
$machine1->waitForUnit("kubernetes.target");
|
|
||||||
$machine2->waitForUnit("kubernetes.target");
|
|
||||||
|
|
||||||
$machine1->waitUntilSucceeds("kubectl get node machine2.my.zyx | grep -w Ready");
|
$machine1->waitUntilSucceeds("kubectl get node machine2.my.zyx | grep -w Ready");
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ let
|
||||||
|
|
||||||
# Only allow the demo data to be used (only if it's unfreeRedistributable).
|
# Only allow the demo data to be used (only if it's unfreeRedistributable).
|
||||||
unfreePredicate = pkg: with pkgs.lib; let
|
unfreePredicate = pkg: with pkgs.lib; let
|
||||||
allowDrvPredicates = [ "quake3-demo" "quake3-pointrelease" ];
|
allowPackageNames = [ "quake3-demodata" "quake3-pointrelease" ];
|
||||||
allowLicenses = [ pkgs.lib.licenses.unfreeRedistributable ];
|
allowLicenses = [ pkgs.lib.licenses.unfreeRedistributable ];
|
||||||
in any (flip hasPrefix pkg.name) allowDrvPredicates &&
|
in elem pkg.pname allowPackageNames &&
|
||||||
elem (pkg.meta.license or null) allowLicenses;
|
elem (pkg.meta.license or null) allowLicenses;
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
|
@ -74,7 +74,7 @@ python3Packages.buildPythonApplication rec {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "A modern audio book player for Linux using GTK+ 3";
|
description = "A modern audio book player for Linux using GTK 3";
|
||||||
homepage = https://cozy.geigi.de/;
|
homepage = https://cozy.geigi.de/;
|
||||||
maintainers = [ maintainers.makefu ];
|
maintainers = [ maintainers.makefu ];
|
||||||
license = licenses.gpl3;
|
license = licenses.gpl3;
|
||||||
|
|
|
@ -27,7 +27,7 @@ stdenv.mkDerivation rec {
|
||||||
description = "PulseAudio Volume Control";
|
description = "PulseAudio Volume Control";
|
||||||
|
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
PulseAudio Volume Control (pavucontrol) provides a GTK+
|
PulseAudio Volume Control (pavucontrol) provides a GTK
|
||||||
graphical user interface to connect to a PulseAudio server and
|
graphical user interface to connect to a PulseAudio server and
|
||||||
easily control the volume of all clients, sinks, etc.
|
easily control the volume of all clients, sinks, etc.
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -46,11 +46,11 @@ python3.pkgs.buildPythonApplication rec {
|
||||||
preFixup = stdenv.lib.optionalString (kakasi != null) "gappsWrapperArgs+=(--prefix PATH : ${kakasi}/bin)";
|
preFixup = stdenv.lib.optionalString (kakasi != null) "gappsWrapperArgs+=(--prefix PATH : ${kakasi}/bin)";
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "GTK+-based audio player written in Python, using the Mutagen tagging library";
|
description = "GTK-based audio player written in Python, using the Mutagen tagging library";
|
||||||
license = licenses.gpl2Plus;
|
license = licenses.gpl2Plus;
|
||||||
|
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Quod Libet is a GTK+-based audio player written in Python, using
|
Quod Libet is a GTK-based audio player written in Python, using
|
||||||
the Mutagen tagging library. It's designed around the idea that
|
the Mutagen tagging library. It's designed around the idea that
|
||||||
you know how to organize your music better than we do. It lets
|
you know how to organize your music better than we do. It lets
|
||||||
you make playlists based on regular expressions (don't worry,
|
you make playlists based on regular expressions (don't worry,
|
||||||
|
|
|
@ -41,7 +41,7 @@ in buildPythonApplication rec {
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Sonata is an elegant client for the Music Player Daemon.
|
Sonata is an elegant client for the Music Player Daemon.
|
||||||
|
|
||||||
Written in Python and using the GTK+ 3 widget set, its features
|
Written in Python and using the GTK 3 widget set, its features
|
||||||
include:
|
include:
|
||||||
|
|
||||||
- Expanded and collapsed views
|
- Expanded and collapsed views
|
||||||
|
|
|
@ -18,7 +18,7 @@ stdenv.mkDerivation rec {
|
||||||
];
|
];
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "A notepad clone for GTK+ 2.0";
|
description = "A notepad clone for GTK 2.0";
|
||||||
homepage = http://tarot.freeshell.org/leafpad;
|
homepage = http://tarot.freeshell.org/leafpad;
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
maintainers = [ maintainers.flosse ];
|
maintainers = [ maintainers.flosse ];
|
||||||
|
|
|
@ -11,13 +11,13 @@ let
|
||||||
archive_fmt = if system == "x86_64-darwin" then "zip" else "tar.gz";
|
archive_fmt = if system == "x86_64-darwin" then "zip" else "tar.gz";
|
||||||
|
|
||||||
sha256 = {
|
sha256 = {
|
||||||
"x86_64-linux" = "1np7j6xv0bxmq7762ml0h6pib8963s2vdmyvigi0fz2iik92zv8z";
|
"x86_64-linux" = "1iz36nhkg78346g5407df6jv4d1ydb22hhgs8hiaxql3hq5z7x3q";
|
||||||
"x86_64-darwin" = "0f87cv1sbcvix9f7hhw0vsypp0bf627xdyh4bmh0g41k17ls8wvc";
|
"x86_64-darwin" = "1iijk0kx90rax39iradbbafyvd3vwnzsgvyb3s13asy42pbhhkky";
|
||||||
}.${system};
|
}.${system};
|
||||||
in
|
in
|
||||||
callPackage ./generic.nix rec {
|
callPackage ./generic.nix rec {
|
||||||
|
|
||||||
version = "1.37.1";
|
version = "1.38.0";
|
||||||
pname = "vscode";
|
pname = "vscode";
|
||||||
|
|
||||||
executableName = "code" + lib.optionalString isInsiders "-insiders";
|
executableName = "code" + lib.optionalString isInsiders "-insiders";
|
||||||
|
|
|
@ -11,13 +11,13 @@ let
|
||||||
archive_fmt = if system == "x86_64-darwin" then "zip" else "tar.gz";
|
archive_fmt = if system == "x86_64-darwin" then "zip" else "tar.gz";
|
||||||
|
|
||||||
sha256 = {
|
sha256 = {
|
||||||
"x86_64-linux" = "0j6188gm66bwffyg0vn3ak8242vs2vb2cw92b9wfkiml6sfg555n";
|
"x86_64-linux" = "09rq5jx7aicwp3qqi5pcv6bmyyp1rm5cfa96hvy3f4grhq1fi132";
|
||||||
"x86_64-darwin" = "0iblg0hn6jdds7d2hzp0icb5yh6hhw3fd5g4iim64ibi7lpwj2cj";
|
"x86_64-darwin" = "1y1lbb3q5myaz7jg21x5sl0in8wr46brqj9zyrg3f16zahsagzr4";
|
||||||
}.${system};
|
}.${system};
|
||||||
in
|
in
|
||||||
callPackage ./generic.nix rec {
|
callPackage ./generic.nix rec {
|
||||||
|
|
||||||
version = "1.37.1";
|
version = "1.38.0";
|
||||||
pname = "vscodium";
|
pname = "vscodium";
|
||||||
|
|
||||||
executableName = "codium";
|
executableName = "codium";
|
||||||
|
|
|
@ -26,7 +26,7 @@ stdenv.mkDerivation {
|
||||||
++ (with perlPackages; [ perl XMLParser ]);
|
++ (with perlPackages; [ perl XMLParser ]);
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "Simple GTK+2 color selector";
|
description = "Simple GTK 2 color selector";
|
||||||
homepage = http://gcolor2.sourceforge.net/;
|
homepage = http://gcolor2.sourceforge.net/;
|
||||||
license = stdenv.lib.licenses.gpl2Plus;
|
license = stdenv.lib.licenses.gpl2Plus;
|
||||||
maintainers = with stdenv.lib.maintainers; [ notthemessiah ];
|
maintainers = with stdenv.lib.maintainers; [ notthemessiah ];
|
||||||
|
|
|
@ -46,11 +46,11 @@ stdenv.mkDerivation rec {
|
||||||
enableParallelBuilding = true;
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "Lightweight GTK+ based image viewer";
|
description = "Lightweight GTK based image viewer";
|
||||||
|
|
||||||
longDescription =
|
longDescription =
|
||||||
''
|
''
|
||||||
Geeqie is a lightweight GTK+ based image viewer for Unix like
|
Geeqie is a lightweight GTK based image viewer for Unix like
|
||||||
operating systems. It features: EXIF, IPTC and XMP metadata
|
operating systems. It features: EXIF, IPTC and XMP metadata
|
||||||
browsing and editing interoperability; easy integration with other
|
browsing and editing interoperability; easy integration with other
|
||||||
software; geeqie works on files and directories, there is no need to
|
software; geeqie works on files and directories, there is no need to
|
||||||
|
|
|
@ -19,7 +19,7 @@ python27Packages.buildPythonApplication rec {
|
||||||
MComix is an user-friendly, customizable image viewer. It is specifically
|
MComix is an user-friendly, customizable image viewer. It is specifically
|
||||||
designed to handle comic books, but also serves as a generic viewer.
|
designed to handle comic books, but also serves as a generic viewer.
|
||||||
It reads images in ZIP, RAR, 7Zip or tar archives as well as plain image
|
It reads images in ZIP, RAR, 7Zip or tar archives as well as plain image
|
||||||
files. It is written in Python and uses GTK+ through the PyGTK bindings,
|
files. It is written in Python and uses GTK through the PyGTK bindings,
|
||||||
and runs on both Linux and Windows.
|
and runs on both Linux and Windows.
|
||||||
|
|
||||||
MComix is a fork of the Comix project, and aims to add bug fixes and
|
MComix is a fork of the Comix project, and aims to add bug fixes and
|
||||||
|
|
|
@ -22,9 +22,9 @@ stdenv.mkDerivation rec {
|
||||||
];
|
];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "A simple GTK+1/2 painting program";
|
description = "A simple GTK painting program";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
mtPaint is a simple GTK+1/2 painting program designed for
|
mtPaint is a simple GTK painting program designed for
|
||||||
creating icons and pixel based artwork. It can edit indexed palette
|
creating icons and pixel based artwork. It can edit indexed palette
|
||||||
or 24 bit RGB images and offers basic painting and palette manipulation
|
or 24 bit RGB images and offers basic painting and palette manipulation
|
||||||
tools. It also has several other more powerful features such as channels,
|
tools. It also has several other more powerful features such as channels,
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "calibre";
|
pname = "calibre";
|
||||||
version = "3.47.0";
|
version = "3.47.1";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://download.calibre-ebook.com/${version}/${pname}-${version}.tar.xz";
|
url = "https://download.calibre-ebook.com/${version}/${pname}-${version}.tar.xz";
|
||||||
sha256 = "0mjj47w9pa7ihycialijrfq2qk107dcxwcwriz3b2mg4lixlawy4";
|
sha256 = "17lz6rawlv268vv8i5kj59rswsipq3c14066adaz1paw54zr62dk";
|
||||||
};
|
};
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
|
@ -105,7 +105,7 @@ mkDerivation rec {
|
||||||
disallowedReferences = [ podofo.dev ];
|
disallowedReferences = [ podofo.dev ];
|
||||||
|
|
||||||
calibreDesktopItem = makeDesktopItem {
|
calibreDesktopItem = makeDesktopItem {
|
||||||
name = "calibre";
|
name = "calibre-gui";
|
||||||
desktopName = "calibre";
|
desktopName = "calibre";
|
||||||
exec = "@out@/bin/calibre --detach %F";
|
exec = "@out@/bin/calibre --detach %F";
|
||||||
genericName = "E-book library management";
|
genericName = "E-book library management";
|
||||||
|
@ -151,7 +151,7 @@ mkDerivation rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
ebookEditDesktopItem = makeDesktopItem {
|
ebookEditDesktopItem = makeDesktopItem {
|
||||||
name = "calibre-edit-ebook";
|
name = "calibre-edit-book";
|
||||||
desktopName = "Edit E-book";
|
desktopName = "Edit E-book";
|
||||||
genericName = "E-book Editor";
|
genericName = "E-book Editor";
|
||||||
comment = "Edit e-books";
|
comment = "Edit e-books";
|
||||||
|
|
|
@ -13,7 +13,7 @@ stdenv.mkDerivation rec {
|
||||||
buildInputs = [ intltool gtk2 xdotool hicolor-icon-theme ];
|
buildInputs = [ intltool gtk2 xdotool hicolor-icon-theme ];
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "Lightweight GTK+ Clipboard Manager";
|
description = "Lightweight GTK Clipboard Manager";
|
||||||
homepage = "http://clipit.rspwn.com";
|
homepage = "http://clipit.rspwn.com";
|
||||||
license = licenses.gpl3;
|
license = licenses.gpl3;
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
|
|
|
@ -28,10 +28,10 @@ stdenv.mkDerivation rec {
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
homepage = https://packages.debian.org/wheezy/epdfview;
|
homepage = https://packages.debian.org/wheezy/epdfview;
|
||||||
description = "A lightweight PDF document viewer using Poppler and GTK+";
|
description = "A lightweight PDF document viewer using Poppler and GTK";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
ePDFView is a free lightweight PDF document viewer using Poppler and
|
ePDFView is a free lightweight PDF document viewer using Poppler and
|
||||||
GTK+ libraries. The aim of ePDFView is to make a simple PDF document
|
GTK libraries. The aim of ePDFView is to make a simple PDF document
|
||||||
viewer, in the lines of Evince but without using the Gnome libraries.
|
viewer, in the lines of Evince but without using the Gnome libraries.
|
||||||
'';
|
'';
|
||||||
license = licenses.gpl2;
|
license = licenses.gpl2;
|
||||||
|
|
|
@ -49,13 +49,13 @@ stdenv.mkDerivation rec {
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
homepage = https://fontmanager.github.io/;
|
homepage = https://fontmanager.github.io/;
|
||||||
description = "Simple font management for GTK+ desktop environments";
|
description = "Simple font management for GTK desktop environments";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Font Manager is intended to provide a way for average users to
|
Font Manager is intended to provide a way for average users to
|
||||||
easily manage desktop fonts, without having to resort to command
|
easily manage desktop fonts, without having to resort to command
|
||||||
line tools or editing configuration files by hand. While designed
|
line tools or editing configuration files by hand. While designed
|
||||||
primarily with the Gnome Desktop Environment in mind, it should
|
primarily with the Gnome Desktop Environment in mind, it should
|
||||||
work well with other Gtk+ desktop environments.
|
work well with other GTK desktop environments.
|
||||||
|
|
||||||
Font Manager is NOT a professional-grade font management solution.
|
Font Manager is NOT a professional-grade font management solution.
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -33,7 +33,7 @@ stdenv.mkDerivation rec {
|
||||||
homepage = https://pwmt.org/projects/girara/;
|
homepage = https://pwmt.org/projects/girara/;
|
||||||
description = "User interface library";
|
description = "User interface library";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
girara is a library that implements a GTK+ based VIM-like user interface
|
girara is a library that implements a GTK based VIM-like user interface
|
||||||
that focuses on simplicity and minimalism.
|
that focuses on simplicity and minimalism.
|
||||||
'';
|
'';
|
||||||
license = licenses.zlib;
|
license = licenses.zlib;
|
||||||
|
|
|
@ -39,7 +39,7 @@ stdenv.mkDerivation rec {
|
||||||
meta = {
|
meta = {
|
||||||
description = "A graphical frontend for libgksu";
|
description = "A graphical frontend for libgksu";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
GKSu is a library that provides a Gtk+ frontend to su and sudo.
|
GKSu is a library that provides a GTK frontend to su and sudo.
|
||||||
It supports login shells and preserving environment when acting as
|
It supports login shells and preserving environment when acting as
|
||||||
a su frontend. It is useful to menu items or other graphical
|
a su frontend. It is useful to menu items or other graphical
|
||||||
programs that need to ask a user's password to run another program
|
programs that need to ask a user's password to run another program
|
||||||
|
|
|
@ -30,7 +30,7 @@ stdenv.mkDerivation rec {
|
||||||
description = "Gnome Completion-Run Utility";
|
description = "Gnome Completion-Run Utility";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
A simple program which provides a "run program" window, featuring a bash-like TAB completion.
|
A simple program which provides a "run program" window, featuring a bash-like TAB completion.
|
||||||
It uses GTK+ interface.
|
It uses GTK interface.
|
||||||
Also, supports CTRL-R / CTRL-S / "!" for searching through history.
|
Also, supports CTRL-R / CTRL-S / "!" for searching through history.
|
||||||
Running commands in a terminal with CTRL-Enter. URL handlers.
|
Running commands in a terminal with CTRL-Enter. URL handlers.
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -16,7 +16,7 @@ stdenv.mkDerivation rec {
|
||||||
hardeningDisable = [ "format" ];
|
hardeningDisable = [ "format" ];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "GTK+-based audio CD player/ripper";
|
description = "GTK-based audio CD player/ripper";
|
||||||
homepage = http://nostatic.org/grip;
|
homepage = http://nostatic.org/grip;
|
||||||
license = stdenv.lib.licenses.gpl2;
|
license = stdenv.lib.licenses.gpl2;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ stdenv.mkDerivation rec {
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "A font selection program for X11 using the GTK 2 toolkit";
|
description = "A font selection program for X11 using the GTK 2 toolkit";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Font selection tool similar to xfontsel implemented using GTK+ 2.
|
Font selection tool similar to xfontsel implemented using GTK 2.
|
||||||
Trivial, but useful nonetheless.
|
Trivial, but useful nonetheless.
|
||||||
'';
|
'';
|
||||||
homepage = http://gtk2fontsel.sourceforge.net/;
|
homepage = http://gtk2fontsel.sourceforge.net/;
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
{ lib
|
||||||
|
, mkDerivation
|
||||||
|
, makeDesktopItem
|
||||||
|
, fetchFromGitLab
|
||||||
|
, qmake
|
||||||
|
# qt
|
||||||
|
, qtbase
|
||||||
|
, qtwebsockets
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
desktopItem = makeDesktopItem {
|
||||||
|
type = "Application";
|
||||||
|
name = "Michabo";
|
||||||
|
desktopName = "Michabo";
|
||||||
|
exec = "Michabo";
|
||||||
|
};
|
||||||
|
|
||||||
|
in mkDerivation rec {
|
||||||
|
pname = "michabo";
|
||||||
|
version = "0.1";
|
||||||
|
|
||||||
|
src = fetchFromGitLab {
|
||||||
|
domain = "git.pleroma.social";
|
||||||
|
owner = "kaniini";
|
||||||
|
repo = "michabo";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "0pl4ymdb36r0kwlclfjjp6b1qml3fm9ql7ag5inprny5y8vcjpzn";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
qmake
|
||||||
|
];
|
||||||
|
buildInputs = [
|
||||||
|
qtbase
|
||||||
|
qtwebsockets
|
||||||
|
];
|
||||||
|
|
||||||
|
qmakeFlags = [ "michabo.pro" "DESTDIR=${placeholder "out"}/bin" ];
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
ln -s ${desktopItem}/share $out/share
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "A native desktop app for Pleroma and Mastodon servers";
|
||||||
|
homepage = "https://git.pleroma.social/kaniini/michabo";
|
||||||
|
license = licenses.gpl3;
|
||||||
|
maintainers = with maintainers; [ fgaz ];
|
||||||
|
platforms = platforms.all;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ buildPythonApplication rec {
|
||||||
access to the graphical desktop via speech and refreshable braille.
|
access to the graphical desktop via speech and refreshable braille.
|
||||||
It works with applications and toolkits that support the Assistive
|
It works with applications and toolkits that support the Assistive
|
||||||
Technology Service Provider Interface (AT-SPI). That includes the GNOME
|
Technology Service Provider Interface (AT-SPI). That includes the GNOME
|
||||||
Gtk+ toolkit, the Java platform's Swing toolkit, LibreOffice, Gecko, and
|
GTK toolkit, the Java platform's Swing toolkit, LibreOffice, Gecko, and
|
||||||
WebKitGtk. AT-SPI support for the KDE Qt toolkit is being pursued.
|
WebKitGtk. AT-SPI support for the KDE Qt toolkit is being pursued.
|
||||||
|
|
||||||
Needs `services.gnome3.at-spi2-core.enable = true;` in `configuration.nix`.
|
Needs `services.gnome3.at-spi2-core.enable = true;` in `configuration.nix`.
|
||||||
|
|
|
@ -21,7 +21,7 @@ stdenv.mkDerivation rec {
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
homepage = https://blog.lxde.org/category/pcmanfm/;
|
homepage = https://blog.lxde.org/category/pcmanfm/;
|
||||||
license = licenses.gpl2Plus;
|
license = licenses.gpl2Plus;
|
||||||
description = "File manager with GTK+ interface";
|
description = "File manager with GTK interface";
|
||||||
maintainers = [ maintainers.ttuegel ];
|
maintainers = [ maintainers.ttuegel ];
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ stdenv.mkDerivation rec {
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
homepage = https://pcman.ptt.cc;
|
homepage = https://pcman.ptt.cc;
|
||||||
license = licenses.gpl2;
|
license = licenses.gpl2;
|
||||||
description = "Telnet BBS browser with GTK+ interface";
|
description = "Telnet BBS browser with GTK interface";
|
||||||
maintainers = [ maintainers.sifmelcara ];
|
maintainers = [ maintainers.sifmelcara ];
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,10 +27,7 @@ stdenv.mkDerivation {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "Simple wrapper around the VTE terminal emulator widget for GTK+";
|
description = "Simple wrapper around the VTE terminal emulator widget for GTK";
|
||||||
longDescription = ''
|
|
||||||
Simple wrapper around the VTE terminal emulator widget for GTK+
|
|
||||||
'';
|
|
||||||
homepage = https://github.com/esmil/stupidterm;
|
homepage = https://github.com/esmil/stupidterm;
|
||||||
license = licenses.lgpl3Plus;
|
license = licenses.lgpl3Plus;
|
||||||
maintainers = [ maintainers.etu ];
|
maintainers = [ maintainers.etu ];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ lib, haskellPackages, fetchFromGitHub }:
|
{ lib, haskellPackages, fetchFromGitHub }:
|
||||||
|
|
||||||
let
|
let
|
||||||
version = "1.6.0";
|
version = "1.6.1";
|
||||||
sha256 = "1yq7lbqg759i3hyxcskx3924b7xmw6i4ny6n8yq80k4hikw2k6mf";
|
sha256 = "047gvpq52pif9sfb4qcfdiwz50x3wlnjvsnnjzypm1qlwyl2rbz1";
|
||||||
|
|
||||||
in (haskellPackages.mkDerivation {
|
in (haskellPackages.mkDerivation {
|
||||||
pname = "taskell";
|
pname = "taskell";
|
||||||
|
|
|
@ -21,7 +21,7 @@ in symlinkJoin {
|
||||||
description = "A highly customizable and functional PDF viewer";
|
description = "A highly customizable and functional PDF viewer";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Zathura is a highly customizable and functional PDF viewer based on the
|
Zathura is a highly customizable and functional PDF viewer based on the
|
||||||
poppler rendering library and the gtk+ toolkit. The idea behind zathura
|
poppler rendering library and the GTK toolkit. The idea behind zathura
|
||||||
is an application that provides a minimalistic and space saving interface
|
is an application that provides a minimalistic and space saving interface
|
||||||
as well as an easy usage that mainly focuses on keyboard interaction.
|
as well as an easy usage that mainly focuses on keyboard interaction.
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -22,7 +22,7 @@ stdenv.mkDerivation rec {
|
||||||
];
|
];
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "Lightweight WebKitGTK+ web browser";
|
description = "Lightweight WebKitGTK web browser";
|
||||||
homepage = https://www.midori-browser.org/;
|
homepage = https://www.midori-browser.org/;
|
||||||
license = with licenses; [ lgpl21Plus ];
|
license = with licenses; [ lgpl21Plus ];
|
||||||
platforms = with platforms; linux;
|
platforms = with platforms; linux;
|
||||||
|
|
|
@ -21,9 +21,9 @@ stdenv.mkDerivation rec {
|
||||||
installFlags = [ "PREFIX=$(out)" ];
|
installFlags = [ "PREFIX=$(out)" ];
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "A simple web browser based on WebKit/GTK+";
|
description = "A simple web browser based on WebKit/GTK";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Surf is a simple web browser based on WebKit/GTK+. It is able to display
|
Surf is a simple web browser based on WebKit/GTK. It is able to display
|
||||||
websites and follow links. It supports the XEmbed protocol which makes it
|
websites and follow links. It supports the XEmbed protocol which makes it
|
||||||
possible to embed it in another application. Furthermore, one can point
|
possible to embed it in another application. Furthermore, one can point
|
||||||
surf to another URI by setting its XProperties.
|
surf to another URI by setting its XProperties.
|
||||||
|
|
|
@ -17,11 +17,11 @@ let
|
||||||
vivaldiName = if isSnapshot then "vivaldi-snapshot" else "vivaldi";
|
vivaldiName = if isSnapshot then "vivaldi-snapshot" else "vivaldi";
|
||||||
in stdenv.mkDerivation rec {
|
in stdenv.mkDerivation rec {
|
||||||
pname = "vivaldi";
|
pname = "vivaldi";
|
||||||
version = "2.7.1628.30-1";
|
version = "2.7.1628.33-1";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://downloads.vivaldi.com/${branch}/vivaldi-${branch}_${version}_amd64.deb";
|
url = "https://downloads.vivaldi.com/${branch}/vivaldi-${branch}_${version}_amd64.deb";
|
||||||
sha256 = "1lz8adwiwll8g246s5pa0ipfraph51s9f4lcfysdrp1s3s1qhw8x";
|
sha256 = "1km5ccxqyd5xgmzm42zca670jf7wd4j7c726fhyj4wjni71zar34";
|
||||||
};
|
};
|
||||||
|
|
||||||
unpackPhase = ''
|
unpackPhase = ''
|
||||||
|
|
|
@ -15,13 +15,13 @@ with lib;
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "kubernetes";
|
pname = "kubernetes";
|
||||||
version = "1.14.3";
|
version = "1.15.3";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "kubernetes";
|
owner = "kubernetes";
|
||||||
repo = "kubernetes";
|
repo = "kubernetes";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "1r31ssf8bdbz8fdsprhkc34jqhz5rcs3ixlf0mbjcbq0xr7y651z";
|
sha256 = "0vamr7m8i5svmvb0z01cngv3sffdfjj0bky2zalm7cfnapib8vz1";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ removeReferencesTo makeWrapper which go rsync go-bindata ];
|
buildInputs = [ removeReferencesTo makeWrapper which go rsync go-bindata ];
|
||||||
|
@ -29,7 +29,10 @@ stdenv.mkDerivation rec {
|
||||||
outputs = ["out" "man" "pause"];
|
outputs = ["out" "man" "pause"];
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
substituteInPlace "hack/lib/golang.sh" --replace "_cgo" ""
|
# go env breaks the sandbox
|
||||||
|
substituteInPlace "hack/lib/golang.sh" \
|
||||||
|
--replace 'echo "$(go env GOHOSTOS)/$(go env GOHOSTARCH)"' 'echo "${go.GOOS}/${go.GOARCH}"'
|
||||||
|
|
||||||
substituteInPlace "hack/update-generated-docs.sh" --replace "make" "make SHELL=${stdenv.shell}"
|
substituteInPlace "hack/update-generated-docs.sh" --replace "make" "make SHELL=${stdenv.shell}"
|
||||||
# hack/update-munge-docs.sh only performs some tests on the documentation.
|
# hack/update-munge-docs.sh only performs some tests on the documentation.
|
||||||
# They broke building k8s; disabled for now.
|
# They broke building k8s; disabled for now.
|
||||||
|
@ -52,13 +55,12 @@ stdenv.mkDerivation rec {
|
||||||
cp build/pause/pause "$pause/bin/pause"
|
cp build/pause/pause "$pause/bin/pause"
|
||||||
cp -R docs/man/man1 "$man/share/man"
|
cp -R docs/man/man1 "$man/share/man"
|
||||||
|
|
||||||
cp cluster/addons/addon-manager/namespace.yaml $out/share
|
|
||||||
cp cluster/addons/addon-manager/kube-addons.sh $out/bin/kube-addons
|
cp cluster/addons/addon-manager/kube-addons.sh $out/bin/kube-addons
|
||||||
patchShebangs $out/bin/kube-addons
|
patchShebangs $out/bin/kube-addons
|
||||||
substituteInPlace $out/bin/kube-addons \
|
|
||||||
--replace /opt/namespace.yaml $out/share/namespace.yaml
|
|
||||||
wrapProgram $out/bin/kube-addons --set "KUBECTL_BIN" "$out/bin/kubectl"
|
wrapProgram $out/bin/kube-addons --set "KUBECTL_BIN" "$out/bin/kubectl"
|
||||||
|
|
||||||
|
cp ${./mk-docker-opts.sh} $out/bin/mk-docker-opts.sh
|
||||||
|
|
||||||
$out/bin/kubectl completion bash > $out/share/bash-completion/completions/kubectl
|
$out/bin/kubectl completion bash > $out/share/bash-completion/completions/kubectl
|
||||||
$out/bin/kubectl completion zsh > $out/share/zsh/site-functions/_kubectl
|
$out/bin/kubectl completion zsh > $out/share/zsh/site-functions/_kubectl
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright 2014 The Kubernetes Authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Generate Docker daemon options based on flannel env file.
|
||||||
|
|
||||||
|
# exit on any error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "$0 [-f FLANNEL-ENV-FILE] [-d DOCKER-ENV-FILE] [-i] [-c] [-m] [-k COMBINED-KEY]
|
||||||
|
|
||||||
|
Generate Docker daemon options based on flannel env file
|
||||||
|
OPTIONS:
|
||||||
|
-f Path to flannel env file. Defaults to /run/flannel/subnet.env
|
||||||
|
-d Path to Docker env file to write to. Defaults to /run/docker_opts.env
|
||||||
|
-i Output each Docker option as individual var. e.g. DOCKER_OPT_MTU=1500
|
||||||
|
-c Output combined Docker options into DOCKER_OPTS var
|
||||||
|
-k Set the combined options key to this value (default DOCKER_OPTS=)
|
||||||
|
-m Do not output --ip-masq (useful for older Docker version)
|
||||||
|
" >/dev/stderr
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
flannel_env="/run/flannel/subnet.env"
|
||||||
|
docker_env="/run/docker_opts.env"
|
||||||
|
combined_opts_key="DOCKER_OPTS"
|
||||||
|
indiv_opts=false
|
||||||
|
combined_opts=false
|
||||||
|
ipmasq=true
|
||||||
|
val=""
|
||||||
|
|
||||||
|
while getopts "f:d:icmk:" opt; do
|
||||||
|
case $opt in
|
||||||
|
f)
|
||||||
|
flannel_env=$OPTARG
|
||||||
|
;;
|
||||||
|
d)
|
||||||
|
docker_env=$OPTARG
|
||||||
|
;;
|
||||||
|
i)
|
||||||
|
indiv_opts=true
|
||||||
|
;;
|
||||||
|
c)
|
||||||
|
combined_opts=true
|
||||||
|
;;
|
||||||
|
m)
|
||||||
|
ipmasq=false
|
||||||
|
;;
|
||||||
|
k)
|
||||||
|
combined_opts_key=$OPTARG
|
||||||
|
;;
|
||||||
|
\?)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $indiv_opts = false ]] && [[ $combined_opts = false ]]; then
|
||||||
|
indiv_opts=true
|
||||||
|
combined_opts=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${flannel_env}" ]]; then
|
||||||
|
source "${flannel_env}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$FLANNEL_SUBNET" ]]; then
|
||||||
|
# shellcheck disable=SC2034 # Variable name referenced in OPT_LOOP below
|
||||||
|
DOCKER_OPT_BIP="--bip=$FLANNEL_SUBNET"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$FLANNEL_MTU" ]]; then
|
||||||
|
# shellcheck disable=SC2034 # Variable name referenced in OPT_LOOP below
|
||||||
|
DOCKER_OPT_MTU="--mtu=$FLANNEL_MTU"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$FLANNEL_IPMASQ" = true ]] && [[ $ipmasq = true ]]; then
|
||||||
|
# shellcheck disable=SC2034 # Variable name referenced in OPT_LOOP below
|
||||||
|
DOCKER_OPT_IPMASQ="--ip-masq=false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval docker_opts="\$${combined_opts_key}"
|
||||||
|
docker_opts+=" "
|
||||||
|
|
||||||
|
echo -n "" >"${docker_env}"
|
||||||
|
|
||||||
|
# OPT_LOOP
|
||||||
|
for opt in $(compgen -v DOCKER_OPT_); do
|
||||||
|
eval val=\$"${opt}"
|
||||||
|
|
||||||
|
if [[ "$indiv_opts" = true ]]; then
|
||||||
|
echo "$opt=\"$val\"" >>"${docker_env}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker_opts+="$val "
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$combined_opts" = true ]]; then
|
||||||
|
echo "${combined_opts_key}=\"${docker_opts}\"" >>"${docker_env}"
|
||||||
|
fi
|
|
@ -97,8 +97,8 @@ in rec {
|
||||||
terraform_0_11-full = terraform_0_11.full;
|
terraform_0_11-full = terraform_0_11.full;
|
||||||
|
|
||||||
terraform_0_12 = pluggable (generic {
|
terraform_0_12 = pluggable (generic {
|
||||||
version = "0.12.7";
|
version = "0.12.8";
|
||||||
sha256 = "09zsak1a9z2mk88vb6xs9jaxfpazhs0p7x68mw62c9mm13m8kq02";
|
sha256 = "1qlhbn6xj2nd8gwr6aiyjsb62qmj4j9jnxab006xgdr1avvl2p67";
|
||||||
patches = [ ./provider-path.patch ];
|
patches = [ ./provider-path.patch ];
|
||||||
passthru = { inherit plugins; };
|
passthru = { inherit plugins; };
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,7 +28,7 @@ stdenv.mkDerivation rec {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "Native Gtk+ Twitter client for the Linux desktop";
|
description = "Native GTK Twitter client for the Linux desktop";
|
||||||
longDescription = "Corebird is a modern, easy and fun Twitter client.";
|
longDescription = "Corebird is a modern, easy and fun Twitter client.";
|
||||||
homepage = https://corebird.baedert.org/;
|
homepage = https://corebird.baedert.org/;
|
||||||
license = stdenv.lib.licenses.gpl3;
|
license = stdenv.lib.licenses.gpl3;
|
||||||
|
|
|
@ -62,7 +62,7 @@ stdenv.mkDerivation {
|
||||||
enableParallelBuilding = true;
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "Modern Jabber/XMPP Client using GTK+/Vala";
|
description = "Modern Jabber/XMPP Client using GTK/Vala";
|
||||||
homepage = https://github.com/dino/dino;
|
homepage = https://github.com/dino/dino;
|
||||||
license = licenses.gpl3;
|
license = licenses.gpl3;
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
|
|
|
@ -27,10 +27,10 @@ in {
|
||||||
pname = "discord-canary";
|
pname = "discord-canary";
|
||||||
binaryName = "DiscordCanary";
|
binaryName = "DiscordCanary";
|
||||||
desktopName = "Discord Canary";
|
desktopName = "Discord Canary";
|
||||||
version = "0.0.95";
|
version = "0.0.96";
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://dl-canary.discordapp.net/apps/linux/0.0.95/discord-canary-0.0.95.tar.gz";
|
url = "https://dl-canary.discordapp.net/apps/linux/0.0.96/discord-canary-0.0.96.tar.gz";
|
||||||
sha256 = "06qhm73kc88pq0lgbi7qjy4gx9ighkmx128fdm1dpzfv62fjdasw";
|
sha256 = "1fxyh9v5xglwbgr5sidn0cv70qpzcd2q240wsv87k3nawhvfcwsp";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}.${branch}
|
}.${branch}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
, gnome2, gtk3, atk, at-spi2-atk, cairo, pango, gdk-pixbuf, glib, freetype, fontconfig
|
, gnome2, gtk3, atk, at-spi2-atk, cairo, pango, gdk-pixbuf, glib, freetype, fontconfig
|
||||||
, dbus, libX11, xorg, libXi, libXcursor, libXdamage, libXrandr, libXcomposite
|
, dbus, libX11, xorg, libXi, libXcursor, libXdamage, libXrandr, libXcomposite
|
||||||
, libXext, libXfixes, libXrender, libXtst, libXScrnSaver, nss, nspr, alsaLib
|
, libXext, libXfixes, libXrender, libXtst, libXScrnSaver, nss, nspr, alsaLib
|
||||||
, cups, expat, udev, libnotify, libuuid
|
, cups, expat, udev, libnotify, libuuid, at-spi2-core
|
||||||
# Unfortunately this also overwrites the UI language (not just the spell
|
# Unfortunately this also overwrites the UI language (not just the spell
|
||||||
# checking language!):
|
# checking language!):
|
||||||
, hunspellDicts, spellcheckerLanguage ? null # E.g. "de_DE"
|
, hunspellDicts, spellcheckerLanguage ? null # E.g. "de_DE"
|
||||||
|
@ -25,6 +25,7 @@ let
|
||||||
alsaLib
|
alsaLib
|
||||||
atk
|
atk
|
||||||
at-spi2-atk
|
at-spi2-atk
|
||||||
|
at-spi2-core
|
||||||
cairo
|
cairo
|
||||||
cups
|
cups
|
||||||
dbus
|
dbus
|
||||||
|
@ -57,11 +58,11 @@ let
|
||||||
|
|
||||||
in stdenv.mkDerivation rec {
|
in stdenv.mkDerivation rec {
|
||||||
pname = "signal-desktop";
|
pname = "signal-desktop";
|
||||||
version = "1.26.2";
|
version = "1.27.1";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://updates.signal.org/desktop/apt/pool/main/s/signal-desktop/signal-desktop_${version}_amd64.deb";
|
url = "https://updates.signal.org/desktop/apt/pool/main/s/signal-desktop/signal-desktop_${version}_amd64.deb";
|
||||||
sha256 = "08qx7k82x6ybqi3lln6ixzmdz4sr8yz8vfx0y408b85wjfc7ncjk";
|
sha256 = "16fg60c5r7zcjs8ya6jk33l5kz8m21y9a1si3i0a2dvyaclz4a3q";
|
||||||
};
|
};
|
||||||
|
|
||||||
phases = [ "unpackPhase" "installPhase" ];
|
phases = [ "unpackPhase" "installPhase" ];
|
||||||
|
|
|
@ -6,21 +6,21 @@
|
||||||
, guileSupport ? true, guile
|
, guileSupport ? true, guile
|
||||||
, luaSupport ? true, lua5
|
, luaSupport ? true, lua5
|
||||||
, perlSupport ? true, perl
|
, perlSupport ? true, perl
|
||||||
, pythonSupport ? true, pythonPackages
|
, pythonSupport ? true, python3Packages
|
||||||
, rubySupport ? true, ruby
|
, rubySupport ? true, ruby
|
||||||
, tclSupport ? true, tcl
|
, tclSupport ? true, tcl
|
||||||
, extraBuildInputs ? []
|
, extraBuildInputs ? []
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (pythonPackages) python;
|
inherit (python3Packages) python;
|
||||||
plugins = [
|
plugins = [
|
||||||
{ name = "perl"; enabled = perlSupport; cmakeFlag = "ENABLE_PERL"; buildInputs = [ perl ]; }
|
{ name = "perl"; enabled = perlSupport; cmakeFlag = "ENABLE_PERL"; buildInputs = [ perl ]; }
|
||||||
{ name = "tcl"; enabled = tclSupport; cmakeFlag = "ENABLE_TCL"; buildInputs = [ tcl ]; }
|
{ name = "tcl"; enabled = tclSupport; cmakeFlag = "ENABLE_TCL"; buildInputs = [ tcl ]; }
|
||||||
{ name = "ruby"; enabled = rubySupport; cmakeFlag = "ENABLE_RUBY"; buildInputs = [ ruby ]; }
|
{ name = "ruby"; enabled = rubySupport; cmakeFlag = "ENABLE_RUBY"; buildInputs = [ ruby ]; }
|
||||||
{ name = "guile"; enabled = guileSupport; cmakeFlag = "ENABLE_GUILE"; buildInputs = [ guile ]; }
|
{ name = "guile"; enabled = guileSupport; cmakeFlag = "ENABLE_GUILE"; buildInputs = [ guile ]; }
|
||||||
{ name = "lua"; enabled = luaSupport; cmakeFlag = "ENABLE_LUA"; buildInputs = [ lua5 ]; }
|
{ name = "lua"; enabled = luaSupport; cmakeFlag = "ENABLE_LUA"; buildInputs = [ lua5 ]; }
|
||||||
{ name = "python"; enabled = pythonSupport; cmakeFlag = "ENABLE_PYTHON"; buildInputs = [ python ]; }
|
{ name = "python"; enabled = pythonSupport; cmakeFlag = "ENABLE_PYTHON3"; buildInputs = [ python ]; }
|
||||||
];
|
];
|
||||||
enabledPlugins = builtins.filter (p: p.enabled) plugins;
|
enabledPlugins = builtins.filter (p: p.enabled) plugins;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
{ callPackage, luaPackages, pythonPackages }:
|
{ callPackage, luaPackages }:
|
||||||
|
|
||||||
{
|
{
|
||||||
weechat-xmpp = callPackage ./weechat-xmpp {
|
|
||||||
inherit (pythonPackages) pydns;
|
|
||||||
};
|
|
||||||
|
|
||||||
weechat-matrix-bridge = callPackage ./weechat-matrix-bridge {
|
weechat-matrix-bridge = callPackage ./weechat-matrix-bridge {
|
||||||
inherit (luaPackages) cjson luaffi;
|
inherit (luaPackages) cjson luaffi;
|
||||||
};
|
};
|
||||||
|
|
||||||
wee-slack = callPackage ./wee-slack {
|
wee-slack = callPackage ./wee-slack { };
|
||||||
inherit pythonPackages;
|
|
||||||
};
|
|
||||||
|
|
||||||
weechat-autosort = callPackage ./weechat-autosort { };
|
weechat-autosort = callPackage ./weechat-autosort { };
|
||||||
|
|
||||||
|
weechat-otr = callPackage ./weechat-otr { };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ stdenv, substituteAll, buildEnv, fetchFromGitHub, pythonPackages }:
|
{ stdenv, substituteAll, buildEnv, fetchFromGitHub, python3Packages }:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "wee-slack";
|
pname = "wee-slack";
|
||||||
|
@ -16,8 +16,8 @@ stdenv.mkDerivation rec {
|
||||||
src = ./libpath.patch;
|
src = ./libpath.patch;
|
||||||
env = "${buildEnv {
|
env = "${buildEnv {
|
||||||
name = "wee-slack-env";
|
name = "wee-slack-env";
|
||||||
paths = with pythonPackages; [ websocket_client six ];
|
paths = with python3Packages; [ websocket_client six ];
|
||||||
}}/${pythonPackages.python.sitePackages}";
|
}}/${python3Packages.python.sitePackages}";
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
{ stdenv, substituteAll, buildEnv, fetchgit, fetchFromGitHub, python3Packages, gmp }:
|
||||||
|
|
||||||
|
let
|
||||||
|
# pure-python-otr (potr) requires an older version of pycrypto, which is
|
||||||
|
# not compatible with pycryptodome. Therefore, the latest patched version
|
||||||
|
# of pycrypto will be fetched from the Debian project.
|
||||||
|
# https://security-tracker.debian.org/tracker/source-package/python-crypto
|
||||||
|
|
||||||
|
pycrypto = python3Packages.buildPythonPackage rec {
|
||||||
|
pname = "pycrypto";
|
||||||
|
version = "2.6.1-10";
|
||||||
|
|
||||||
|
src = fetchgit {
|
||||||
|
url = "https://salsa.debian.org/sramacher/python-crypto.git";
|
||||||
|
rev = "debian/${version}";
|
||||||
|
sha256 = "10rgq8bmjfpiqqa1g1p1hh7pxlxs7x0nawvk6zip0pd6x2vsr661";
|
||||||
|
};
|
||||||
|
|
||||||
|
buildInputs = [ gmp ];
|
||||||
|
|
||||||
|
preConfigure = ''
|
||||||
|
sed -i 's,/usr/include,/no-such-dir,' configure
|
||||||
|
sed -i "s!,'/usr/include/'!!" setup.py
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
potr = python3Packages.potr.overridePythonAttrs (oldAttrs: {
|
||||||
|
propagatedBuildInputs = [ pycrypto ];
|
||||||
|
});
|
||||||
|
in stdenv.mkDerivation rec {
|
||||||
|
pname = "weechat-otr";
|
||||||
|
version = "1.9.2";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
repo = pname;
|
||||||
|
owner = "mmb";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "1lngv98y6883vk8z2628cl4d5y8jxy39w8245gjdvshl8g18k5s2";
|
||||||
|
};
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
(substituteAll {
|
||||||
|
src = ./libpath.patch;
|
||||||
|
env = "${buildEnv {
|
||||||
|
name = "weechat-otr-env";
|
||||||
|
paths = [ potr pycrypto ];
|
||||||
|
}}/${python3Packages.python.sitePackages}";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
passthru.scripts = [ "weechat_otr.py" ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/share
|
||||||
|
cp weechat_otr.py $out/share/weechat_otr.py
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with stdenv.lib; {
|
||||||
|
homepage = "https://github.com/mmb/weechat-otr";
|
||||||
|
license = licenses.gpl3;
|
||||||
|
maintainers = with maintainers; [ geistesk ];
|
||||||
|
description = "WeeChat script for Off-the-Record messaging";
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/weechat_otr.py b/weechat_otr.py
|
||||||
|
index 0ccfb35..c42bebf 100644
|
||||||
|
--- a/weechat_otr.py
|
||||||
|
+++ b/weechat_otr.py
|
||||||
|
@@ -41,6 +41,8 @@ import shlex
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
|
+sys.path.append('@env@')
|
||||||
|
+
|
||||||
|
import potr
|
||||||
|
import weechat
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
{ stdenv, fetchFromGitHub, xmpppy, pydns, substituteAll, buildEnv }:
|
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
name = "weechat-jabber-2017-08-30";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
repo = "weechat-xmpp";
|
|
||||||
owner = "sleduc";
|
|
||||||
sha256 = "0s02xs0ynld9cxxzj07al364sfglyc5ir1i82133mq0s8cpphnxv";
|
|
||||||
rev = "8f6c21f5a160c9318c7a2d8fd5dcac7ab2e0d843";
|
|
||||||
};
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/share
|
|
||||||
cp jabber.py $out/share/jabber.py
|
|
||||||
'';
|
|
||||||
|
|
||||||
patches = [
|
|
||||||
(substituteAll {
|
|
||||||
src = ./libpath.patch;
|
|
||||||
env = "${buildEnv {
|
|
||||||
name = "weechat-xmpp-env";
|
|
||||||
paths = [ pydns xmpppy ];
|
|
||||||
}}/lib/python2.7/site-packages";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
passthru.scripts = [ "jabber.py" ];
|
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
|
||||||
description = "A fork of the jabber plugin for weechat";
|
|
||||||
homepage = "https://github.com/sleduc/weechat-xmpp";
|
|
||||||
maintainers = with maintainers; [ ma27 ];
|
|
||||||
license = licenses.gpl3Plus;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
diff --git a/jabber.py b/jabber.py
|
|
||||||
index 27006a3..e53c2c0 100644
|
|
||||||
--- a/jabber.py
|
|
||||||
+++ b/jabber.py
|
|
||||||
@@ -95,6 +95,11 @@ SCRIPT_COMMAND = SCRIPT_NAME
|
|
||||||
import re
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
+import sys
|
|
||||||
+
|
|
||||||
+sys.path.append('@env@')
|
|
||||||
+
|
|
||||||
+
|
|
||||||
import_ok = True
|
|
||||||
|
|
||||||
try:
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ lib, runCommand, writeScriptBin, buildEnv
|
{ lib, runCommand, writeScriptBin, buildEnv
|
||||||
, pythonPackages, perlPackages, runtimeShell
|
, python3Packages, perlPackages, runtimeShell
|
||||||
}:
|
}:
|
||||||
|
|
||||||
weechat:
|
weechat:
|
||||||
|
@ -17,11 +17,11 @@ let
|
||||||
in rec {
|
in rec {
|
||||||
python = (simplePlugin "python") // {
|
python = (simplePlugin "python") // {
|
||||||
extraEnv = ''
|
extraEnv = ''
|
||||||
export PATH="${pythonPackages.python}/bin:$PATH"
|
export PATH="${python3Packages.python}/bin:$PATH"
|
||||||
'';
|
'';
|
||||||
withPackages = pkgsFun: (python // {
|
withPackages = pkgsFun: (python // {
|
||||||
extraEnv = ''
|
extraEnv = ''
|
||||||
export PYTHONHOME="${pythonPackages.python.withPackages pkgsFun}"
|
export PYTHONHOME="${python3Packages.python.withPackages pkgsFun}"
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,7 @@ stdenv.mkDerivation rec {
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
homepage = https://astroidmail.github.io/;
|
homepage = https://astroidmail.github.io/;
|
||||||
description = "GTK+ frontend to the notmuch mail system";
|
description = "GTK frontend to the notmuch mail system";
|
||||||
maintainers = with maintainers; [ bdimcheff SuprDewd ];
|
maintainers = with maintainers; [ bdimcheff SuprDewd ];
|
||||||
license = licenses.gpl3Plus;
|
license = licenses.gpl3Plus;
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
|
|
|
@ -50,7 +50,7 @@ stdenv.mkDerivation rec {
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "An app to send/receive SMS, make USSD requests, control mobile data usage and more";
|
description = "An app to send/receive SMS, make USSD requests, control mobile data usage and more";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
A simple GTK+ based GUI compatible with Modem manager, Wader and oFono
|
A simple GTK based GUI compatible with Modem manager, Wader and oFono
|
||||||
system services able to control EDGE/3G/4G broadband modem specific
|
system services able to control EDGE/3G/4G broadband modem specific
|
||||||
functions. You can check balance of your SIM card, send or receive SMS
|
functions. You can check balance of your SIM card, send or receive SMS
|
||||||
messages, control mobile traffic consumption and more.
|
messages, control mobile traffic consumption and more.
|
||||||
|
|
|
@ -38,7 +38,7 @@ stdenv.mkDerivation {
|
||||||
enableParallelBuilding = true;
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "A GTK+-based Usenet newsreader good at both text and binaries";
|
description = "A GTK-based Usenet newsreader good at both text and binaries";
|
||||||
homepage = http://pan.rebelbase.com/;
|
homepage = http://pan.rebelbase.com/;
|
||||||
maintainers = [ stdenv.lib.maintainers.eelco ];
|
maintainers = [ stdenv.lib.maintainers.eelco ];
|
||||||
platforms = stdenv.lib.platforms.linux;
|
platforms = stdenv.lib.platforms.linux;
|
||||||
|
|
|
@ -49,7 +49,7 @@ stdenv.mkDerivation rec {
|
||||||
on top of a cross-platform back-end.
|
on top of a cross-platform back-end.
|
||||||
Feature spotlight:
|
Feature spotlight:
|
||||||
* Uses fewer resources than other clients
|
* Uses fewer resources than other clients
|
||||||
* Native Mac, GTK+ and Qt GUI clients
|
* Native Mac, GTK and Qt GUI clients
|
||||||
* Daemon ideal for servers, embedded systems, and headless use
|
* Daemon ideal for servers, embedded systems, and headless use
|
||||||
* All these can be remote controlled by Web and Terminal clients
|
* All these can be remote controlled by Web and Terminal clients
|
||||||
* Bluetack (PeerGuardian) blocklists with automatic updates
|
* Bluetack (PeerGuardian) blocklists with automatic updates
|
||||||
|
|
|
@ -52,7 +52,7 @@ stdenv.mkDerivation rec {
|
||||||
meta = {
|
meta = {
|
||||||
license = licenses.gpl2;
|
license = licenses.gpl2;
|
||||||
homepage = https://gitlab.com/Remmina/Remmina;
|
homepage = https://gitlab.com/Remmina/Remmina;
|
||||||
description = "Remote desktop client written in GTK+";
|
description = "Remote desktop client written in GTK";
|
||||||
maintainers = with maintainers; [ melsigl ryantm ];
|
maintainers = with maintainers; [ melsigl ryantm ];
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,7 +61,7 @@ in stdenv.mkDerivation {
|
||||||
Its goal is to be an easy-to-use no-nonsense cross-platform
|
Its goal is to be an easy-to-use no-nonsense cross-platform
|
||||||
project management application.
|
project management application.
|
||||||
|
|
||||||
Planner is a GTK+ application written in C and licensed under the
|
Planner is a GTK application written in C and licensed under the
|
||||||
GPLv2 or any later version. It can store its data in either xml
|
GPLv2 or any later version. It can store its data in either xml
|
||||||
files or in a postgresql database. Projects can also be printed
|
files or in a postgresql database. Projects can also be printed
|
||||||
to PDF or exported to HTML for easy viewing from any web browser.
|
to PDF or exported to HTML for easy viewing from any web browser.
|
||||||
|
|
|
@ -21,7 +21,7 @@ in stdenv.mkDerivation {
|
||||||
description = "Real time satellite tracking and orbit prediction";
|
description = "Real time satellite tracking and orbit prediction";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Gpredict is a real time satellite tracking and orbit prediction program
|
Gpredict is a real time satellite tracking and orbit prediction program
|
||||||
written using the Gtk+ widgets. Gpredict is targetted mainly towards ham radio
|
written using the GTK widgets. Gpredict is targetted mainly towards ham radio
|
||||||
operators but others interested in satellite tracking may find it useful as
|
operators but others interested in satellite tracking may find it useful as
|
||||||
well. Gpredict uses the SGP4/SDP4 algorithms, which are compatible with the
|
well. Gpredict uses the SGP4/SDP4 algorithms, which are compatible with the
|
||||||
NORAD Keplerian elements.
|
NORAD Keplerian elements.
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
{buildPythonPackage, lib, fetchFromGitHub, statistics}:
|
||||||
|
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "xenomapper";
|
||||||
|
version = "1.0.2";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "genomematt";
|
||||||
|
repo = pname;
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "0mnmfzlq5mhih6z8dq5bkx95vb8whjycz9mdlqwbmlqjb3gb3zhr";
|
||||||
|
};
|
||||||
|
|
||||||
|
propagatedBuildInputs = [ statistics ];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "http://github.com/genomematt/xenomapper";
|
||||||
|
description = "A utility for post processing mapped reads that have been aligned to a primary genome and a secondary genome and binning reads into species specific, multimapping in each species, unmapped and unassigned bins";
|
||||||
|
license = licenses.gpl3;
|
||||||
|
platforms = platforms.all;
|
||||||
|
maintainers = [ maintainers.jbedo ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ pythonPackages.buildPythonApplication rec {
|
||||||
description = "A handy file search tool";
|
description = "A handy file search tool";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Catfish is a handy file searching tool. The interface is
|
Catfish is a handy file searching tool. The interface is
|
||||||
intentionally lightweight and simple, using only GTK+3.
|
intentionally lightweight and simple, using only GTK 3.
|
||||||
You can configure it to your needs by using several command line
|
You can configure it to your needs by using several command line
|
||||||
options.
|
options.
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -51,7 +51,7 @@ stdenv.mkDerivation rec {
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "Simple GTK+ frontend for the mpv video player";
|
description = "Simple GTK frontend for the mpv video player";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
GNOME MPV interacts with mpv via the client API exported by libmpv,
|
GNOME MPV interacts with mpv via the client API exported by libmpv,
|
||||||
allowing access to mpv's powerful playback capabilities through an
|
allowing access to mpv's powerful playback capabilities through an
|
||||||
|
|
|
@ -97,7 +97,7 @@ stdenv.mkDerivation rec {
|
||||||
and containers. Very versatile and customizable.
|
and containers. Very versatile and customizable.
|
||||||
Package provides:
|
Package provides:
|
||||||
CLI - `HandbrakeCLI`
|
CLI - `HandbrakeCLI`
|
||||||
GTK+ GUI - `ghb`
|
GTK GUI - `ghb`
|
||||||
'';
|
'';
|
||||||
license = licenses.gpl2;
|
license = licenses.gpl2;
|
||||||
maintainers = with maintainers; [ Anton-Latukha wmertens ];
|
maintainers = with maintainers; [ Anton-Latukha wmertens ];
|
||||||
|
|
|
@ -13,13 +13,13 @@ with stdenv.lib;
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "mkvtoolnix";
|
pname = "mkvtoolnix";
|
||||||
version = "36.0.0";
|
version = "37.0.0";
|
||||||
|
|
||||||
src = fetchFromGitLab {
|
src = fetchFromGitLab {
|
||||||
owner = "mbunkus";
|
owner = "mbunkus";
|
||||||
repo = "mkvtoolnix";
|
repo = "mkvtoolnix";
|
||||||
rev = "release-${version}";
|
rev = "release-${version}";
|
||||||
sha256 = "114j9n2m6dkh7vqzyhcsjzzffadr0lzyjmh31cbl4mvvkg9j5z6r";
|
sha256 = "0r1qzvqc6xx7rmv4v4fjc70cqy832h8v0fjf6c5ljbg1c6pgkl0l";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
|
|
@ -49,9 +49,9 @@ stdenv.mkDerivation {
|
||||||
configureFlags = [ "--disable-debug" ];
|
configureFlags = [ "--disable-debug" ];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "GTK+3 application to edit video subtitles";
|
description = "GTK 3 application to edit video subtitles";
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
Subtitle Editor is a GTK+3 tool to edit subtitles for GNU/Linux/*BSD. It
|
Subtitle Editor is a GTK 3 tool to edit subtitles for GNU/Linux/*BSD. It
|
||||||
can be used for new subtitles or as a tool to transform, edit, correct
|
can be used for new subtitles or as a tool to transform, edit, correct
|
||||||
and refine existing subtitle. This program also shows sound waves, which
|
and refine existing subtitle. This program also shows sound waves, which
|
||||||
makes it easier to synchronise subtitles to voices.
|
makes it easier to synchronise subtitles to voices.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue