import from nix-scripts

This commit is contained in:
Sebastien Bourdeauducq 2020-06-20 17:54:21 +08:00
commit 5a0afc48d4
40 changed files with 2978 additions and 0 deletions

View File

@ -0,0 +1,54 @@
{ config, pkgs, lib, ... }:
with lib;
let
makeBackup = pkgs.writeScript "make-backup" ''
#!${pkgs.bash}/bin/bash
set -e
umask 0077
DBDUMPDIR=`mktemp -d`
pushd $DBDUMPDIR
${config.services.mysql.package}/bin/mysqldump --single-transaction flarum > flarum.sql
${pkgs.sudo}/bin/sudo -u mattermost ${config.services.postgresql.package}/bin/pg_dump mattermost > mattermost.sql
${pkgs.gnutar}/bin/tar cf - --exclude "/var/lib/gitea/repositories/*/*.git/archives" /etc/nixos /var/lib/gitea flarum.sql mattermost.sql | \
${pkgs.bzip2}/bin/bzip2 | \
${pkgs.gnupg}/bin/gpg --symmetric --batch --passphrase-file /etc/nixos/secret/backup-passphrase | \
${pkgs.rclone}/bin/rclone rcat --config /etc/nixos/secret/rclone.conf dropbox:backup-`date +%F`.tar.bz2.gpg
popd
rm -rf $DBDUMPDIR
echo Backup done
'';
cfg = config.services.mlabs-backup;
in
{
options.services.mlabs-backup = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable backups";
};
};
config = mkIf cfg.enable {
systemd.services.mlabs-backup = {
description = "M-Labs backup";
serviceConfig = {
Type = "oneshot";
User = "root";
Group = "root";
ExecStart = "${makeBackup}";
};
};
systemd.timers.mlabs-backup = {
description = "M-Labs backup";
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "weekly";
};
};
}

View File

@ -0,0 +1,667 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, ... }:
let
netifWan = "enp0s31f6";
netifLan = "enp3s0";
netifWifi = "wlp1s0";
netifSit = "henet0";
hydraWwwOutputs = "/var/www/hydra-outputs";
in
{
imports =
[
./hardware-configuration.nix
./homu/nixos-module.nix
./backup-module.nix
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/v2.3.0/nixos-mailserver-v2.3.0.tar.gz";
sha256 = "0lpz08qviccvpfws2nm83n7m2r8add2wvfg9bljx9yxx8107r919";
})
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.blacklistedKernelModules = ["iwlwifi"];
security.apparmor.enable = true;
networking = {
hostName = "nixbld";
firewall = {
allowedTCPPorts = [ 80 443 ];
allowedUDPPorts = [ 53 67 ];
trustedInterfaces = [ netifLan ];
};
interfaces."${netifLan}" = {
ipv4.addresses = [{
address = "192.168.1.1";
prefixLength = 24;
}];
ipv6.addresses = [{
address = "2001:470:f821:1::";
prefixLength = 64;
}];
};
interfaces."${netifWifi}" = {
ipv4.addresses = [{
address = "192.168.12.1";
prefixLength = 24;
}];
ipv6.addresses = [{
address = "2001:470:f821:2::";
prefixLength = 64;
}];
};
nat = {
enable = true;
externalInterface = netifWan;
internalInterfaces = [ netifLan netifWifi ];
forwardPorts = [
{ sourcePort = 2201; destination = "192.168.1.201:22"; proto = "tcp"; }
{ sourcePort = 2202; destination = "192.168.1.202:22"; proto = "tcp"; }
{ sourcePort = 2203; destination = "192.168.1.203:22"; proto = "tcp"; }
{ sourcePort = 2204; destination = "192.168.1.204:22"; proto = "tcp"; }
{ sourcePort = 2205; destination = "192.168.1.205:22"; proto = "tcp"; }
];
extraCommands = ''
iptables -w -N block-lan-from-wifi
iptables -w -A block-lan-from-wifi -i ${netifLan} -o ${netifWifi} -j DROP
iptables -w -A block-lan-from-wifi -i ${netifWifi} -o ${netifLan} -j DROP
iptables -w -A FORWARD -j block-lan-from-wifi
'';
extraStopCommands = ''
iptables -w -D FORWARD -j block-lan-from-wifi 2>/dev/null|| true
iptables -w -F block-lan-from-wifi 2>/dev/null|| true
iptables -w -X block-lan-from-wifi 2>/dev/null|| true
'';
};
sits."${netifSit}" = {
dev = netifWan;
remote = "216.218.221.6";
local = "42.200.147.171";
ttl = 255;
};
interfaces."${netifSit}".ipv6 = {
addresses = [{ address = "2001:470:18:629::2"; prefixLength = 64; }];
routes = [{ address = "::"; prefixLength = 0; }];
};
};
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = "1";
boot.kernel.sysctl."net.ipv6.conf.default.forwarding" = "1";
services.unbound = {
enable = true;
extraConfig =
''
server:
port: 5353
'';
};
services.hostapd = {
enable = true;
interface = netifWifi;
hwMode = "g";
ssid = "M-Labs";
wpaPassphrase = (import /etc/nixos/secret/wifi_password.nix);
extraConfig = ''
ieee80211d=1
country_code=HK
ieee80211n=1
wmm_enabled=1
auth_algs=1
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
'';
};
services.dnsmasq = {
enable = true;
servers = ["::1#5353"];
extraConfig = ''
interface=${netifLan}
interface=${netifWifi}
bind-interfaces
dhcp-range=interface:${netifLan},192.168.1.81,192.168.1.254,24h
dhcp-range=interface:${netifWifi},192.168.12.10,192.168.12.254,24h
enable-ra
dhcp-range=interface:${netifLan},::,constructor:${netifLan},ra-names
dhcp-range=interface:${netifWifi},::,constructor:${netifWifi},ra-only
no-resolv
# Static IPv4s to make Red Pitayas less annoying
dhcp-host=rp-f05cc9,192.168.1.190
dhcp-host=rp-f0612e,192.168.1.191
# Static IPv4s to make port redirections work
dhcp-host=rpi-1,192.168.1.201
dhcp-host=rpi-2,192.168.1.202
dhcp-host=rpi-3,192.168.1.203
dhcp-host=rpi-4,192.168.1.204
dhcp-host=rpi-5,192.168.1.205
# Default IP addresses for ARTIQ boards
address=/thermostat/192.168.1.26
address=/kc705/192.168.1.50
address=/zc706/192.168.1.51
address=/zc706-2/192.168.1.52
address=/sayma/192.168.1.60
address=/metlino/192.168.1.65
address=/kasli/192.168.1.70
address=/kasli-customer/192.168.1.75
address=/stabilizer-customer/192.168.1.76
# uTCA MCH from NAT
address=/tschernobyl/192.168.1.80
'';
};
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "de";
};
# Set your time zone.
time.timeZone = "Asia/Hong_Kong";
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
wget vim git file lm_sensors acpi pciutils psmisc telnet nixops
irssi tmux usbutils imagemagick jq zip unzip
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = { enable = true; enableSSHSupport = true; };
# List services that you want to enable:
services.apcupsd.enable = true;
services.apcupsd.configText = ''
UPSTYPE usb
NISIP 127.0.0.1
BATTERYLEVEL 10
MINUTES 5
'';
# Enable the OpenSSH daemon.
services.openssh.enable = true;
services.openssh.forwardX11 = true;
services.openssh.passwordAuthentication = false;
programs.mosh.enable = true;
programs.fish.enable = true;
# Enable CUPS to print documents.
services.avahi.enable = true;
services.avahi.interfaces = [ netifLan ];
services.avahi.publish.enable = true;
services.avahi.publish.userServices = true;
nixpkgs.config.allowUnfree = true;
services.printing.enable = true;
services.printing.drivers = [ pkgs.hplipWithPlugin ];
services.printing.browsing = true;
services.printing.listenAddresses = [ "*:631" ];
services.printing.defaultShared = true;
hardware.sane.enable = true;
hardware.sane.extraBackends = [ pkgs.hplipWithPlugin ];
users.extraGroups.plugdev = { };
users.extraUsers.sb = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout" "lp" "scanner"];
shell = pkgs.fish;
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyPk5WyFoWSvF4ozehxcVBoZ+UHgrI7VW/OoQfFFwIQe0qvetUZBMZwR2FwkLPAMZV8zz1v4EfncudEkVghy4P+/YVLlDjqDq9zwZnh8Nd/ifu84wmcNWHT2UcqnhjniCdshL8a44memzABnxfLLv+sXhP2x32cJAamo5y6fukr2qLp2jbXzR+3sv3klE0ruUXis/BR1lLqNJEYP8jB6fLn2sLKinnZPfn6DwVOk10mGeQsdME/eGl3phpjhODH9JW5V2V5nJBbC0rBnq+78dyArKVqjPSmIcSy72DEIpTctnMEN1W34BGrnsDd5Xd/DKxKxHKTMCHtZRwLC2X0NWN"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCMALVC8RDTHec+PC8y1s3tcpUAODgq6DEzQdHDf/cyvDMfmCaPiMxfIdmkns5lMa03hymIfSmLUF0jFFDc7biRp7uf9AAXNsrTmplHii0l0McuOOZGlSdZM4eL817P7UwJqFMxJyFXDjkubhQiX6kp25Kfuj/zLnupRCaiDvE7ho/xay6Jrv0XLz935TPDwkc7W1asLIvsZLheB+sRz9SMOb9gtrvk5WXZl5JTOFOLu+JaRwQLHL/xdcHJTOod7tqHYfpoC5JHrEwKzbhTOwxZBQBfTQjQktKENQtBxXHTe71rUEWfEZQGg60/BC4BrRmh4qJjlJu3v4VIhC7SSHn1"
];
};
users.extraUsers.rj = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout"];
};
users.extraUsers.astro = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
shell = pkgs.bashInteractive;
};
users.extraUsers.nix = {
isNormalUser = true;
};
security.sudo.wheelNeedsPassword = false;
security.hideProcessInformation = true;
boot.kernel.sysctl."kernel.dmesg_restrict" = true;
services.udev.packages = [ pkgs.sane-backends ];
nix.distributedBuilds = true;
nix.buildMachines = [
{
hostName = "localhost";
maxJobs = 4;
system = "x86_64-linux";
supportedFeatures = ["big-parallel"];
}
{
hostName = "rpi-3";
sshUser = "nix";
sshKey = "/etc/nixos/secret/nix_id_rsa";
maxJobs = 1;
system = "aarch64-linux";
}
];
services.hydra = {
enable = true;
package = pkgs.hydra-unstable;
useSubstitutes = true;
hydraURL = "https://nixbld.m-labs.hk";
notificationSender = "hydra@m-labs.hk";
minimumDiskFree = 15; # in GB
minimumDiskFreeEvaluator = 1;
extraConfig =
''
binary_cache_secret_key_file = /etc/nixos/secret/nixbld.m-labs.hk-1
max_output_size = 10000000000
<runcommand>
job = web:web:web
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/web
</runcommand>
<runcommand>
job = artiq:full:sipyco-manual-html
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/sipyco-manual-html
</runcommand>
<runcommand>
job = artiq:full:sipyco-manual-latexpdf
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/sipyco-manual-latexpdf
</runcommand>
<runcommand>
job = artiq:full-beta:artiq-manual-html
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-html-beta
</runcommand>
<runcommand>
job = artiq:full-beta:artiq-manual-latexpdf
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-latexpdf-beta
</runcommand>
<runcommand>
job = artiq:full-beta:conda-channel
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-conda-channel-beta
</runcommand>
<runcommand>
job = artiq:full:artiq-manual-html
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-html
</runcommand>
<runcommand>
job = artiq:full:artiq-manual-latexpdf
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-latexpdf
</runcommand>
<runcommand>
job = artiq:full:conda-channel
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-conda-channel
</runcommand>
'';
};
systemd.services.hydra-www-outputs-init = {
description = "Set up a hydra-owned directory for build outputs";
wantedBy = [ "multi-user.target" ];
requiredBy = [ "hydra-queue-runner.service" ];
before = [ "hydra-queue-runner.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = [ "${pkgs.coreutils}/bin/mkdir -p ${hydraWwwOutputs}" "${pkgs.coreutils}/bin/chown hydra-queue-runner:hydra ${hydraWwwOutputs}" ];
};
};
nix.extraOptions = ''
secret-key-files = /etc/nixos/secret/nixbld.m-labs.hk-1
'';
nix.sandboxPaths = ["/opt"];
services.munin-node.enable = true;
services.munin-cron = {
enable = true;
hosts = ''
[${config.networking.hostName}]
address localhost
'';
};
services.mlabs-backup.enable = true;
services.gitea = {
enable = true;
httpPort = 3001;
rootUrl = "https://git.m-labs.hk/";
appName = "M-Labs Git";
cookieSecure = true;
disableRegistration = true;
mailerPasswordFile = "/etc/nixos/secret/mailerpassword";
extraConfig =
''
[mailer]
ENABLED = true
HOST = ssl.serverraum.org:587
FROM = sysop@m-labs.hk
USER = sysop@m-labs.hk
[service]
ENABLE_NOTIFY_MAIL = true
[attachment]
ALLOWED_TYPES = */*
'';
};
systemd.tmpfiles.rules = [
"L+ '${config.services.gitea.stateDir}/custom/templates/home.tmpl' - - - - ${./gitea-home.tmpl}"
];
services.mattermost = {
enable = true;
siteUrl = "https://chat.m-labs.hk/";
mutableConfig = true;
};
services.matterbridge = {
enable = true;
configPath = "/etc/nixos/secret/matterbridge.toml";
};
nixpkgs.config.packageOverrides = super: let self = super.pkgs; in {
hydra-unstable = super.hydra-unstable.overrideAttrs(oa: {
patches = oa.patches or [] ++ [ ./hydra-conda.patch ./hydra-retry.patch ./hydra-unbreak-sysbuild.patch ];
hydraPath = oa.hydraPath + ":" + super.lib.makeBinPath [ super.jq ];
});
matterbridge = super.matterbridge.overrideAttrs(oa: {
patches = oa.patches or [] ++ [ ./matterbridge-disable-github.patch ];
});
};
security.acme.acceptTerms = true;
security.acme.email = "sb" + "@m-labs.hk";
security.acme.certs = {
"nixbld.m-labs.hk" = {
group = "nginx";
user = "nginx";
webroot = "/var/lib/acme/acme-challenge";
extraDomains = {
"m-labs.hk" = null;
"www.m-labs.hk" = null;
"conda.m-labs.hk" = null;
"lab.m-labs.hk" = null;
"git.m-labs.hk" = null;
"chat.m-labs.hk" = null;
"hooks.m-labs.hk" = null;
"forum.m-labs.hk" = null;
"perso.m-labs.hk" = null;
"nmigen.org" = null;
"www.nmigen.org" = null;
"openhardware.hk" = null;
"git.openhardware.hk" = null;
};
};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedGzipSettings = true;
virtualHosts = let
mainWebsite = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "${hydraWwwOutputs}/web";
extraConfig = ''
error_page 404 /404.html;
'';
locations."^~ /fonts/".extraConfig = ''
expires 60d;
'';
locations."^~ /js/".extraConfig = ''
expires 60d;
'';
locations."/MathJax/" = {
alias = "/var/www/MathJax/";
extraConfig = ''
expires 60d;
'';
};
# legacy URLs, redirect to avoid breaking people's bookmarks
locations."/gateware.html".extraConfig = ''
return 301 /gateware/migen/;
'';
locations."/migen".extraConfig = ''
return 301 /gateware/migen/;
'';
locations."/artiq".extraConfig = ''
return 301 /experiment-control/artiq/;
'';
locations."/artiq/resources.html".extraConfig = ''
return 301 /experiment-control/resources/;
'';
# autogenerated manuals
locations."/artiq/sipyco-manual/" = {
alias = "${hydraWwwOutputs}/sipyco-manual-html/share/doc/sipyco-manual/html/";
};
locations."=/artiq/sipyco-manual.pdf" = {
alias = "${hydraWwwOutputs}/sipyco-manual-latexpdf/share/doc/sipyco-manual/SiPyCo.pdf";
};
locations."/artiq/manual-beta/" = {
alias = "${hydraWwwOutputs}/artiq-manual-html-beta/share/doc/artiq-manual/html/";
};
locations."=/artiq/manual-beta.pdf" = {
alias = "${hydraWwwOutputs}/artiq-manual-latexpdf-beta/share/doc/artiq-manual/ARTIQ.pdf";
};
locations."/artiq/manual/" = {
alias = "${hydraWwwOutputs}/artiq-manual-html/share/doc/artiq-manual/html/";
};
locations."=/artiq/manual.pdf" = {
alias = "${hydraWwwOutputs}/artiq-manual-latexpdf/share/doc/artiq-manual/ARTIQ.pdf";
};
# legacy content
locations."/migen/manual/" = {
alias = "/var/www/m-labs.hk.old/migen/manual/";
};
locations."/artiq/manual-release-4/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-4/";
};
locations."/artiq/manual-release-3/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-3/";
};
locations."/artiq/manual-release-2/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-2/";
};
};
in {
"m-labs.hk" = mainWebsite;
"www.m-labs.hk" = mainWebsite;
"lab.m-labs.hk" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/munin/".alias = "/var/www/munin/";
locations."/munin".extraConfig = ''
auth_basic "Munin";
auth_basic_user_file /etc/nixos/secret/muninpasswd;
'';
locations."/homu/".proxyPass = "http://127.0.0.1:54856/";
};
"nixbld.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3000";
};
"conda.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/artiq-beta/" = {
alias = "${hydraWwwOutputs}/artiq-conda-channel-beta/";
extraConfig = ''
autoindex on;
index bogus_index_file;
'';
};
locations."/artiq/" = {
alias = "${hydraWwwOutputs}/artiq-conda-channel/";
extraConfig = ''
autoindex on;
index bogus_index_file;
'';
};
};
"git.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3001";
extraConfig = ''
client_max_body_size 300M;
'';
};
"chat.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:8065";
locations."~ /api/v[0-9]+/(users/)?websocket$".proxyPass = "http://127.0.0.1:8065";
locations."~ /api/v[0-9]+/(users/)?websocket$".proxyWebsockets = true;
};
"hooks.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/mattermost-github".extraConfig = ''
include ${pkgs.nginx}/conf/uwsgi_params;
uwsgi_pass unix:${config.services.uwsgi.runDir}/uwsgi-mgi.sock;
'';
locations."/rfq".extraConfig = ''
include ${pkgs.nginx}/conf/uwsgi_params;
uwsgi_pass unix:${config.services.uwsgi.runDir}/uwsgi-rfq.sock;
'';
};
"forum.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "/var/www/flarum/public";
locations."~ \.php$".extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.flarum.socket};
fastcgi_index index.php;
'';
extraConfig = ''
index index.php;
include /var/www/flarum/.nginx.conf;
'';
};
"perso.m-labs.hk" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "/var/www/perso";
};
"nmigen.org" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".extraConfig = ''
return 307 https://m-labs.hk/gateware/nmigen/;
'';
};
"www.nmigen.org" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".extraConfig = ''
return 307 https://m-labs.hk/gateware/nmigen/;
'';
};
"git.openhardware.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3002";
extraConfig = ''
client_max_body_size 300M;
'';
};
};
};
services.uwsgi = {
enable = true;
plugins = [ "python3" ];
instance = {
type = "emperor";
vassals = {
mattermostgithub = import ./mattermost-github-integration/uwsgi-config.nix { inherit config pkgs; };
rfq = import ./rfq/uwsgi-config.nix { inherit config pkgs; };
};
};
};
services.mysql = {
enable = true;
package = pkgs.mariadb;
};
services.phpfpm.pools.flarum = {
user = "nobody";
settings = {
"listen.owner" = "nginx";
"listen.group" = "nginx";
"listen.mode" = "0600";
"pm" = "dynamic";
"pm.max_children" = 5;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
"pm.max_requests" = 500;
};
};
services.homu = {
enable = true;
config = "/etc/nixos/secret/homu.toml";
};
mailserver = {
enable = true;
localDnsResolver = false; # conflicts with dnsmasq
# Some mail servers do reverse DNS lookups to filter spam.
# Getting a proper reverse DNS record from ISP is difficult, so use whatever already exists.
fqdn = "42-200-147-171.static.imsbiz.com";
domains = [ "nmigen.org" ];
loginAccounts = (import /etc/nixos/secret/email_accounts.nix);
certificateScheme = 3;
};
security.acme.certs."${config.mailserver.fqdn}".extraDomains = {
"mail.nmigen.org" = null;
};
containers.openhardwarehk = {
autoStart = true;
config =
{ config, pkgs, ... }:
{
services.gitea = {
enable = true;
httpPort = 3002;
rootUrl = "https://git.openhardware.hk/";
appName = "Open Hardware HK";
cookieSecure = true;
disableRegistration = true;
extraConfig =
''
[attachment]
ALLOWED_TYPES = */*
'';
};
};
};
# This value determines the NixOS release with which your system is to be
# compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you
# should.
system.stateVersion = "18.09"; # Did you read the comment?
}

View File

@ -0,0 +1,23 @@
{{template "base/head" .}}
<div class="home">
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div>
<img class="logo" src="{{AppSubUrl}}/img/gitea-lg.png" />
</div>
<div class="hero">
<h1 class="ui icon header title">
{{AppName}}
</h1>
</div>
</div>
</div>
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center column">
<p class="large">
Welcome! This Gitea instance is here to support projects related to <a href="https://m-labs.hk">M-Labs</a>. You may want to browse the <a href="https://git.m-labs.hk/M-Labs/">M-Labs organization</a> where many projects are located. If you would like an account (we give them to anyone who wants to contribute on projects related to Sinara, ARTIQ, nMigen, etc.), simply write a short email to sb@m-***.hk stating the username you would like to have.
</p>
</div>
</div>
</div>
{{template "base/footer" .}}

View File

@ -0,0 +1,13 @@
diff --git a/homu/git_helper.py b/homu/git_helper.py
index 0f70c69..f53fb57 100755
--- a/homu/git_helper.py
+++ b/homu/git_helper.py
@@ -7,7 +7,7 @@ SSH_KEY_FILE = os.path.join(os.path.dirname(__file__), '../cache/key')
def main():
- args = ['ssh', '-i', SSH_KEY_FILE, '-S', 'none'] + sys.argv[1:]
+ args = ['ssh', '-o', 'StrictHostKeyChecking=no', '-i', SSH_KEY_FILE, '-S', 'none'] + sys.argv[1:]
os.execvp('ssh', args)

View File

@ -0,0 +1,52 @@
{ config, pkgs, lib, ... }:
with lib;
let
homu = pkgs.callPackage ./pkg.nix {};
cfg = config.services.homu;
in
{
options.services.homu = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the bot";
};
dbDir = mkOption {
type = types.str;
default = "/var/db/homu";
description = "Path to the database file (use the same path in config.toml)";
};
config = mkOption {
description = "Location of config.toml";
type = types.str;
};
};
config = mkIf cfg.enable {
users.users.homu = {
group = "homu";
home = cfg.dbDir;
createHome = true;
};
users.groups.homu = {};
systemd.services.homu = {
description = "Homu bot";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${homu}/bin/homu -c ${cfg.config}";
Restart = "always";
RestartSec = "5sec";
User = "homu";
Group = "homu";
};
};
};
}

View File

@ -0,0 +1,26 @@
diff --git a/homu/git_helper.py b/homu/git_helper.py
index 0f70c69..732230c 100755
--- a/homu/git_helper.py
+++ b/homu/git_helper.py
@@ -3,7 +3,7 @@
import sys
import os
-SSH_KEY_FILE = os.path.join(os.path.dirname(__file__), '../cache/key')
+SSH_KEY_FILE = os.path.expanduser("~/cache/key")
def main():
diff --git a/homu/main.py b/homu/main.py
index 16b60a2..a2e109a 100644
--- a/homu/main.py
+++ b/homu/main.py
@@ -649,7 +649,7 @@ def git_push(git_cmd, branch, state):
def init_local_git_cmds(repo_cfg, git_cfg):
- fpath = 'cache/{}/{}'.format(repo_cfg['owner'], repo_cfg['name'])
+ fpath = '{}/cache/{}/{}'.format(os.path.expanduser("~"), repo_cfg['owner'], repo_cfg['name'])
url = 'git@github.com:{}/{}.git'.format(repo_cfg['owner'], repo_cfg['name']) # noqa
if not os.path.exists(SSH_KEY_FILE):

View File

@ -0,0 +1,34 @@
{ python3Packages, python3, fetchFromGitHub, git, openssh }:
let
uritemplate_0_2_0 = python3Packages.github3_py.overrideAttrs(oa: rec {
version = "0.2.0";
src = python3Packages.fetchPypi {
pname = "uritemplate.py";
inherit version;
sha256 = "1pfk04pmnysz0383lwzgig8zqlwiv2n4pmq51f0mc60zz1jimq4g";
};
});
github3_py_0_9_6 = python3Packages.github3_py.overrideAttrs(oa: rec {
version = "0.9.6";
src = python3Packages.fetchPypi {
pname = "github3.py";
inherit version;
sha256 = "1i8xnh586z4kka7pjl7cy08fmzjs14c8jdp8ykb9jjpzsy2xncdq";
};
propagatedBuildInputs = [ python3Packages.requests uritemplate_0_2_0 ];
});
in
python3Packages.buildPythonApplication {
name = "homu";
src = fetchFromGitHub {
owner = "servo";
repo = "homu";
rev = "2ea53e76ebac3e5fa11bc39054b3cd4c42eff607";
sha256 = "1ih7s8zfbpq0qb9vqbxzr0r4s9ff52l4ipr916kwbck3ygliq3r9";
};
patches = [ ./patch-cache-directory.patch ./disable-ssh-host-keycheck.patch ];
postInstall = "chmod 755 $out/${python3.sitePackages}/homu/git_helper.py";
propagatedBuildInputs = [ github3_py_0_9_6 git openssh ] ++ (with python3Packages; [ toml jinja2 requests bottle waitress retrying ]);
checkPhase = "python -m unittest discover tests -v";
}

View File

@ -0,0 +1,47 @@
commit 5aa5f8d5742883d41d7278a2c8bc2c9a2ddfef45
Author: Sebastien Bourdeauducq <sb@m-labs.hk>
Date: Sun Apr 14 18:25:27 2019 +0800
add SVG icon for conda package
diff --git a/src/root/product-list.tt b/src/root/product-list.tt
index 298d0a66..85914bbd 100644
--- a/src/root/product-list.tt
+++ b/src/root/product-list.tt
@@ -157,6 +157,11 @@
<img src="[% c.uri_for("/static/images/debian.png") %]" alt="DEB" />
</td>
<td>Debian package</td>
+ [% CASE "conda" %]
+ <td>
+ <img src="[% c.uri_for("/static/images/conda.svg") %]" width="32" height="32" alt="Conda" />
+ </td>
+ <td>Conda package</td>
[% CASE "iso" %]
<td>
<img src="[% c.uri_for("/static/images/iso.png") %]" alt="ISO" />
diff --git a/src/root/static/images/conda.svg b/src/root/static/images/conda.svg
new file mode 100644
index 00000000..67859731
--- /dev/null
+++ b/src/root/static/images/conda.svg
@@ -0,0 +1,18 @@
+<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g id="g2">
+ <g>
+ <path d="M118.89,75.13c-1.31-2.72-3.46-5.53-6.97-7.33c-2.37-1.48-4.57-2.24-6.01-2.63 c1.53-5.6-0.64-10.06-3.69-13.39c-4.53-4.88-9.27-5.59-9.27-5.59l-0.01,0c1.56-3.03,2.15-6.54,1.36-9.99 c-1-4.26-3.29-6.94-6.31-8.73c-3.09-1.83-6.91-2.73-10.83-3.43c-1.88-0.34-9.81-1.45-13.1-6c-2.65-3.69-2.73-10.33-3.45-12.32 c-0.77-2.05-3.38-1.15-6.23,0.76c-3.33,2.22-10.23,9.35-12.89,16.49c-2.03,5.47-2.08,10.21-1.28,13.89 c-3.29,0.55-5.76,1.66-6.23,1.88c-0.16,0.05-0.32,0.1-0.49,0.17c-3.01,1.24-9.43,7.02-10.01,15.85c-0.2,3.14,0.21,6.31,1.2,9.26 c-3.94,1.1-6.22,2.54-6.26,2.57c-2,0.75-5.18,2.95-6.15,4.13c-1.97,2.38-3.34,5.21-4.15,8.18C6.35,85.36,7,92.71,10.14,98.67 c1.74,3.31,4.12,6.83,6.74,9.52c8.55,8.79,23.31,12.11,34.96,14.03c14.19,2.34,29.05,1.52,42.33-3.97 c19.92-8.22,25.22-21.44,26-25.17C121.92,84.77,119.8,77,118.89,75.13z" style="fill:#865D53;"/>
+ <g>
+ <g>
+ <ellipse cx="85.95" cy="66.39" rx="16.61" ry="15.5" style="fill:#FFFFFF;" transform="matrix(0.1106 -0.9939 0.9939 0.1106 10.453 144.4706)"/>
+ <path d="M92.63,66.36c-0.23,3.3-3.14,5.82-6.49,5.62c-3.36-0.19-5.9-3.04-5.67-6.34 c0.22-3.31,3.12-5.82,6.48-5.62C90.31,60.21,92.86,63.06,92.63,66.36" style="fill:#2F2F2F;"/>
+ </g>
+ <g>
+ <ellipse cx="42.46" cy="66.4" rx="15.5" ry="16.61" style="fill:#FFFFFF;" transform="matrix(0.9972 -0.0752 0.0752 0.9972 -4.8714 3.3796)"/>
+ <path d="M49.02,65.13c0.38,3.29-2.01,6.3-5.34,6.72c-3.34,0.43-6.36-1.9-6.74-5.18 c-0.4-3.29,1.99-6.3,5.33-6.73C45.6,59.52,48.63,61.85,49.02,65.13" style="fill:#2F2F2F;"/>
+ </g>
+ </g>
+ <path d="M87.35,89.46c-2.22-1.5-5.02-0.51-7.49,0c-6.9,1.42-12.95,1.48-15.86,1.48 c-2.91,0-8.96-0.06-15.86-1.48c-2.47-0.51-5.27-1.5-7.49,0c-2.82,1.9-0.74,8.74,3.7,13.36c2.68,2.79,9.07,8.21,19.66,8.21 c10.58,0,16.97-5.42,19.66-8.21C88.09,98.2,90.17,91.37,87.35,89.46z" style="fill:#ED6D31;"/>
+ </g>
+ </g>
+</svg>
\ No newline at end of file

View File

@ -0,0 +1,19 @@
commit 86bf81c0b8a51bffa4b4b566e1caaac6f0e041d3
Author: Sebastien Bourdeauducq <sb@m-labs.hk>
Date: Thu Mar 14 17:45:32 2019 +0800
add option to disable retries on transient failures
diff --git a/src/hydra-queue-runner/build-remote.cc b/src/hydra-queue-runner/build-remote.cc
index 69c430eb..bdbc808d 100644
--- a/src/hydra-queue-runner/build-remote.cc
+++ b/src/hydra-queue-runner/build-remote.cc
@@ -344,7 +344,7 @@ void State::buildRemote(ref<Store> destStore,
break;
case BuildResult::TransientFailure:
result.stepStatus = bsFailed;
- result.canRetry = true;
+ result.canRetry = get(step->drv->env, "__hydraRetry").value_or("1") == "1";
result.errorMsg = "";
break;
case BuildResult::TimedOut:

View File

@ -0,0 +1,25 @@
diff --git a/src/lib/Hydra/Schema/Builds.pm b/src/lib/Hydra/Schema/Builds.pm
index d4334300..014d07ce 100644
--- a/src/lib/Hydra/Schema/Builds.pm
+++ b/src/lib/Hydra/Schema/Builds.pm
@@ -608,6 +608,7 @@ makeQueries('', "");
makeQueries('ForProject', "and project = ?");
makeQueries('ForJobset', "and jobset_id = ?");
makeQueries('ForJob', "and jobset_id = ? and job = ?");
+makeQueries('ForJobName', "and jobset_id = (select id from jobsets j where j.name = ?) and job = ?");
my %hint = (
diff --git a/src/script/hydra-eval-jobset b/src/script/hydra-eval-jobset
index ea336bfc..2f208418 100755
--- a/src/script/hydra-eval-jobset
+++ b/src/script/hydra-eval-jobset
@@ -142,7 +142,7 @@ sub fetchInputSystemBuild {
$projectName ||= $project->name;
$jobsetName ||= $jobset->name;
- my @latestBuilds = $db->resultset('LatestSucceededForJob')
+ my @latestBuilds = $db->resultset('LatestSucceededForJobName')
->search({}, {bind => [$jobsetName, $jobName]});
my @validBuilds = ();

View File

@ -0,0 +1,15 @@
diff --git a/bridge/mattermost/helpers.go b/bridge/mattermost/helpers.go
index 14b7469d..d9b77bdf 100644
--- a/bridge/mattermost/helpers.go
+++ b/bridge/mattermost/helpers.go
@@ -206,6 +206,10 @@ func (b *Bmattermost) skipMessage(message *matterclient.Message) bool {
return true
}
+ if message.Username == "github" {
+ return true
+ }
+
// if the message has reactions don't repost it (for now, until we can correlate reaction with message)
if message.Post.HasReactions {
return true

View File

@ -0,0 +1,32 @@
{ fetchFromGitHub, python3Packages }:
with python3Packages;
buildPythonPackage rec {
pname = "mattermost-github-integration";
version = "0.0.0-unstable";
src = fetchFromGitHub {
owner = "softdevteam";
repo = "mattermost-github-integration";
rev = "1124a0ff233b50ed6070cb84cfffd128ad219831";
sha256 = "1hfvjaxjhliy8sv9j3616fkdwd2jqhfsj9ai7ggx88zhxknrfx85";
};
propagatedBuildInputs = [
appdirs
click
flask
itsdangerous
jinja2
markupsafe
olefile
packaging
pillow
pyparsing
requests
six
werkzeug
];
checkInputs = [
pytest
];
doCheck = true;
}

View File

@ -0,0 +1,15 @@
{ config, pkgs }:
let
pkg = pkgs.callPackage ./pkg.nix {};
in {
type = "normal";
pythonPackages = self: [ pkg ];
module = "mattermostgithub:app";
env = [
"MGI_CONFIG_FILE=${./../secret/mattermost-github-integration.py}"
];
socket = "${config.services.uwsgi.runDir}/uwsgi-mgi.sock";
# allow access from nginx
chmod-socket = 666;
}

View File

@ -0,0 +1,93 @@
{ config, pkgs, lib, ... }:
with lib;
let
notifico = (pkgs.callPackage ./pkg.nix {})
.overrideAttrs (attrs: {
buildInputs = attrs.buildInputs ++ [ pkgs.makeWrapper ];
# Extend the module path so that local_config.py can be found
postInstall = ''
${attrs.postInstall}
wrapProgram $out/bin/notifico \
--set PYTHONPATH "$${PYTHONPATH}:${cfg.dbDir}"
'';
});
cfg = config.services.notifico;
in
{
options.services.notifico = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the commit notification service";
};
enableLocalRedis = mkOption {
type = types.bool;
default = true;
description = "Enable a local Redis server";
};
dbDir = mkOption {
type = types.str;
default = "/var/db/notifico";
description = "Home directory and location of the database file";
};
config = mkOption {
description = "Path to local_config.py, https://github.com/notifico/notifico/raw/master/notifico/config.py";
type = types.str;
};
};
config = mkIf cfg.enable {
users.users.notifico = {
group = "notifico";
home = cfg.dbDir;
createHome = true;
};
users.groups.notifico = {};
services.redis = mkIf cfg.enableLocalRedis {
enable = true;
bind = "127.0.0.1";
};
systemd.services =
let
User = "notifico";
Group = "notifico";
WorkingDirectory = "${cfg.dbDir}";
ExecStartPre = [
"${pkgs.coreutils}/bin/rm -f local_config.pyc"
"${pkgs.coreutils}/bin/ln -sf ${cfg.config} local_config.py"
];
notifico-init = {
description = "Notifico initialization";
serviceConfig = {
inherit User Group WorkingDirectory ExecStartPre;
Type = "oneshot";
ExecStart = "${notifico}/bin/notifico init";
};
};
notificoService = component: {
description = "Notifico ${component}";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "notifico-init.service" ];
requires = [ "notifico-init.service" ];
serviceConfig = {
inherit User Group WorkingDirectory ExecStartPre;
Type = "simple";
ExecStart = "${notifico}/bin/notifico ${component}";
Restart = "always";
RestartSec = "5sec";
};
};
in {
inherit notifico-init;
notifico-www = notificoService "www";
notifico-worker = notificoService "worker";
notifico-bots = notificoService "bots";
};
};
}

View File

@ -0,0 +1,107 @@
{ python2Packages, python2, fetchFromGitHub, fetchurl }:
let
Flask-Gravatar = python2Packages.buildPythonPackage {
name = "Flask-Gravatar";
src = python2Packages.fetchPypi {
pname = "Flask-Gravatar";
version = "0.5.0";
sha256 = "1qb2ylirjajdqsmldhwfdhf8i86k7vlh3y4gnqfqj4n6q8qmyrk0";
};
propagatedBuildInputs = with python2Packages; [
pytestrunner
flask
];
checkInputs = with python2Packages; [
check-manifest
coverage
isort
pydocstyle
pytestcache
pytestcov
pytestpep8
pytest
pygments
];
};
utopia = python2Packages.buildPythonPackage {
name = "utopia";
src = fetchFromGitHub {
owner = "notifico";
repo = "utopia";
rev = "70293ed5e1ca55232e0fae71061e7e9b9b29be6f";
sha256 = "11cnh9l4d9jlhafnfis9si6kgk9zsdd5439qnhxh6dca3x4a986q";
};
propagatedBuildInputs = with python2Packages; [
gevent
blinker
];
doCheck = false;
};
Flask-WTF = python2Packages.flask_wtf.overrideAttrs(oa: rec {
version = "0.8.4";
src = python2Packages.fetchPypi {
pname = "Flask-WTF";
inherit version;
sha256 = "1khbwmlrcnk9f46f7kf531n06pkyfs6nc8fk273js9mj2igngg2y";
};
});
Flask-XML-RPC = python2Packages.flask_wtf.overrideAttrs(oa: rec {
version = "0.1.2";
src = python2Packages.fetchPypi {
pname = "Flask-XML-RPC";
inherit version;
sha256 = "1dwalj7pc5iid9l1k50q5mllirnn9f5s7jq54a66x48a4j179p2a";
};
});
in
python2Packages.buildPythonApplication {
name = "notifico";
src = fetchFromGitHub {
owner = "notifico";
repo = "notifico";
rev = "6af849e4c75dff4d740051676f5a2093a44efcee";
sha256 = "18jifqdvjy4x5s1bh7vx501pin52g4n3hhw1z4m2c0h512z4spdr";
};
patches = [
(fetchurl {
url = https://github.com/whitequark/notifico/commit/22b582fad6cb97af6f7437e8462d720ddacc42ef.patch;
sha256 = "0w8i8hf1r8b0p1y1zn9vyvnyi20qp120aiyalqymhsxsh17mma52";
})
];
propagatedBuildInputs = with python2Packages; [
flask
Flask-WTF
Flask-Gravatar
flask_sqlalchemy
Flask-XML-RPC
flask_mail
flask-caching
Fabric
sqlalchemy
utopia
gevent
oauth2
redis
gunicorn
requests
PyGithub
xmltodict
unidecode
raven
blinker
docopt
celery
];
postInstall = ''
mkdir $out/bin
cat << EOF > $out/bin/notifico
#!${python2}/bin/python
import sys
from notifico.__main__ import main
sys.exit(main(sys.argv))
EOF
chmod +x $out/bin/notifico
'';
}

View File

@ -0,0 +1,9 @@
{ python3Packages, runCommand }:
# Note: we do not use fetchgit but a local copy instead to avoid
# chicken-and-egg problem if reinstalling nixbld.m-labs.hk from scratch.
with python3Packages; buildPythonPackage rec {
name = "rfq";
src = ./src;
propagatedBuildInputs = [ flask flask_mail python-dotenv ];
}

View File

@ -0,0 +1,10 @@
blinker
click
Flask
Flask-Mail
itsdangerous
Jinja2
MarkupSafe
python-dotenv
six
Werkzeug

View File

@ -0,0 +1,75 @@
from os import getenv
from dotenv import load_dotenv
from flask import Flask
from flask import current_app
from flask import json
from flask import jsonify
from flask import make_response
from flask import request
from flask_mail import Mail
from flask_mail import Message
from werkzeug.middleware.proxy_fix import ProxyFix
load_dotenv()
app = Flask(__name__)
app.config.update(
DEBUG=getenv("FLASK_DEBUG") == "True",
MAIL_SERVER=getenv("FLASK_MAIL_SERVER"),
MAIL_PORT=getenv("FLASK_MAIL_PORT"),
MAIL_USE_SSL=getenv("FLASK_MAIL_USE_SSL"),
MAIL_DEBUG=False,
MAIL_USERNAME=getenv("FLASK_MAIL_USERNAME"),
MAIL_PASSWORD=getenv("FLASK_MAIL_PASSWORD"),
MAIL_RECIPIENT=getenv("FLASK_MAIL_RECIPIENT"),
MAIL_SENDER=getenv("FLASK_MAIL_SENDER")
)
app.wsgi_app = ProxyFix(app.wsgi_app)
mail = Mail(app)
@app.after_request
def after(response):
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Headers"] = "*"