Pythonhack och NixOS

Jag hackade nyligen ihop ett program som läser in ett API och presenterar detta som en ATOM/RSS-feed. Det blev inte snyggt, men nu kan jag följa en blogg som normalt saknar ett RSS-flöde i min RSS-läsare.

Det trixigaste var att lyckas förstå hur en kör ett program som detta i NixOS, men utan att behöva stöka allt för mycket. Jag ville att skriptet ska köras varje timme och jag ville använda några förpaketerade paketberoenden. I korthet, Nix-Writers fixade biffen!

{ pkgs, ... }:
let
  python-hack = pkgs.writers.writePython3 "pythonhack" {
    libraries = [ pkgs.python3Packages.feedgen pkgs.python3Packages.requests ];
  } (builtins.readFile "/path/to/script.py");
in {
  systemd.services.python-hack = {
    description = "hack hack hack";
    serviceConfig = {
      Type = "oneshot";
      User = "foobar";
      ExecStart = python-hack; # samma namn som i let-blocket
    };
  };
  systemd.timers.python-hack = {
    wantedBy = [ "timers.target" ];
    partOf = [ "python-hack.service" ];
    timerConfig.OnCalendar = "hourly";
  };
}

Det är nog lite hackigt att använda writers-funktionaliteten såhär, det är nog tänkt att användas för att skriva programkod direkt i nix-filen, istället för att bara läsa in källkoden från en fil som här ovan. Men det fungerade, och det var relativt enkelt att sätta ihop.

Huawei E3372 & Linux

Det här är mest en anteckning till den framtida Oscar, och eventuella andra intresserade.

Jag har ett USB-modem jag använder med mina datorer hemma, ett Huawei E3372. Det startar först upp som en CD-enhet för att dela med sig av sina drivrutiner, och behöver sedan instrueras att byta läge till ett vanligt modem.

För detta skapade jag en udev-regel som gör det jobbet åt mig, ersätt sökvägar med vad som är korrekt för din Linux:

ATTR{idVendor}=="12d1", ATTR{idProduct}=="14fe", RUN+="${pkgs.usb_modeswitch}/bin/usb_modeswitch -v 12d1 -p 14fe -V 12d1 -P 1506 -J"

Du kommer behöva programmet usb_modeswitch, som verkar finnas paketerad för de flesta distros.

Alla ID:n och liknande fås av att köra en lsusb. Innan modemet bytt läge:

Bus 002 Device 016: ID 12d1:14dc Huawei Technologies Co., Ltd.

Efter att den bytt läge:

Bus 001 Device 006: ID 12d1:1506 Huawei Technologies Co., Ltd. Modem/Networkcard

För mig startade inte modem-manager (som krävs, och är en del av network-manager) automagiskt, så jag lade till en extra udev-regel för att fixa detta när modemet (i rätt läge) ansluts:

ATTR{idVendor}=="12d1", ATTR{idProduct}=="1506", RUN+="${pkgs.systemd}/bin/systemctl restart modem-manager.service"

Nu behöver jag bara be network-manager att koppla upp sig på 4G. Klart!

Göra backuper i NixOS

Ingen behöver nog påminnas om vikten av backuper, men ibland behöver en kanske påminnas om hur en går till väga för att göra det, särskilt för smalare distributioner som NixOS.

Read More

Note to self: NixOS och paket från master

Jag har börjat använda NixOS på rätt många av mina datorer och jag gillar det verkligen, även om det huvudsakligen är känslomässiga argument jag använder mig av. Mer om detta i ett annat inlägg, detta inlägg är mest för att själv komma ihåg hur jag gjorde för att installera hugo (som tidigare byggde denna hemsida) från mästergrenen för nixpkgs.

nix-env -f https://github.com/NixOS/nixpkgs/archive/master.tar.gz -iA hugo

Klart.

En deklarativ uppdatering

Ett lite mer deklarativt sätt att göra det på är såhär:

environment.systemPackages =
let
  unstableSrc = pkgs.fetchFromGitHub {
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "b332924e6aac9e34168f43cf7db5181bcd01f0e5";
    sha256 = "025vac8h89jvikm6c2mlrzv7p57j9rwkkpnshaq1fw63pcn8dpqf";
  };
  unstable = import unstableSrc {};
  stable = import <nixpkgs> {};
in [
  unstable.hugo
  stable.wget stable.curl
];

Det här är fortfarande så pass nytt och obekant att jag behövde rätt lång tid på mig för att klura ut det här. Jag misstänker att det även går att lösa på ett betydligt elegantare sätt, men dit har jag inte riktigt kommit än. 🙂

Det går även att göra såhär:

environment.systemPackages =
  let
    stable = import <nixpkgs> {};
    unstable = import (fetchTarball "https://nixos.org/channels/nixos-unstable/nixexpr
s.tar.xz") {};
  in [ stable.wget stable.curl unstable.hugo ];

Lite mindre stök, men även lite mindre deterministiskt vilket annars är lite av styrkan med denna distribution.

Närmare nirvana

Den här varianten är förvisso lite längre än den senaste, men känns ändå lite…bättre! Varianten nedan är givetvis stulen från någon annan vänlig själ på StackOverflow.

Namnet inom vinkeljärnen nedan ska motsvaras av namnet på en kanal, som du exempelvis kan definiera såhär:

nix-channel --add https://nixos.org/channels/nixos-unstable nixos-unstable
nix-channel --update

Och sedan, i din /etc/nixos/configuration.nix:

# Credit: https://stackoverflow.com/a/47571488
nixpkgs.config = 
{
    # Allow proprietary packages
    allowUnfree = true;

    # Create an alias for the unstable channel
    packageOverrides = pkgs: 
    {
        unstable = import <nixos-unstable> 
            { 
                # pass the nixpkgs config to the unstable alias
                # to ensure `allowUnfree = true;` is propagated:
                config = config.nixpkgs.config; 
            };
    };
};

Nu är det bara att använda unstable som prefix för de paket du vill ha från den ostadiga grenen. Om du inte kört en nix-channel --update är det värt att göra det innan du försöker dig på en nixos-rebuild dry-run, annars kommer det inte går att bygga om systemet.

Vill du förresten göra livet lite bekvämare rekommenderar jag följande:

environment.systemPackages = with pkgs; [ wget curl unstable.hugo ];

Nu slipper du även skriva prefixet för de stadiga paketen!