Compare commits
5 Commits
gitea-acti
...
4826af5e0c
| Author | SHA1 | Date | |
|---|---|---|---|
|
4826af5e0c
|
|||
|
302afec109
|
|||
|
1d14b691a8
|
|||
|
fbd9d709da
|
|||
|
a85aad433f
|
@@ -14,11 +14,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: https://gitea.com/actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install nix
|
- uses: cachix/install-nix-action@v23
|
||||||
uses: https://github.com/cachix/install-nix-action@v23
|
|
||||||
with:
|
|
||||||
github_access_token: ${{ secrets.INPUT_GITHUB_ACCESS_TOKEN }}
|
|
||||||
- name: Check ${{ matrix.check }}
|
- name: Check ${{ matrix.check }}
|
||||||
# Depends on nixos/nix#7759 to simply `nix flake check`
|
# Depends on nixos/nix#7759 to simply `nix flake check`
|
||||||
run: nix run .#checks.$(nix eval --raw --impure --expr "builtins.currentSystem").${{ matrix.check }}
|
run: nix run .#checks.$(nix eval --raw --impure --expr "builtins.currentSystem").${{ matrix.check }}
|
||||||
@@ -46,13 +43,13 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: https://gitea.com/actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install nix
|
- name: Install nix
|
||||||
uses: https://github.com/cachix/install-nix-action@v23
|
uses: cachix/install-nix-action@v23
|
||||||
- name: Show nixpkgs version
|
- name: Show nixpkgs version
|
||||||
run: nix eval --impure --expr '(import ./flake-compat.nix { src = ./.; }).lib.version'
|
run: nix eval --impure --expr '(import ./flake-compat.nix { src = ./.; }).lib.version'
|
||||||
- name: Setup cachix
|
- name: Setup cachix
|
||||||
uses: https://github.com/cachix/cachix-action@v12
|
uses: cachix/cachix-action@v12
|
||||||
if: ${{ matrix.cachixName != '<YOUR_CACHIX_NAME>' }}
|
if: ${{ matrix.cachixName != '<YOUR_CACHIX_NAME>' }}
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.cachixName }}
|
name: ${{ matrix.cachixName }}
|
||||||
6
flake.lock
generated
6
flake.lock
generated
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1699725108,
|
"lastModified": 1696725822,
|
||||||
"narHash": "sha256-NTiPW4jRC+9puakU4Vi8WpFEirhp92kTOSThuZke+FA=",
|
"narHash": "sha256-B7uAOS7TkLlOg1aX01rQlYbydcyB6ZnLJSfaYbKVww8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "911ad1e67f458b6bcf0278fa85e33bb9924fed7e",
|
"rev": "5aabb5780a11c500981993d49ee93cfa6df9307b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
amdgpu-pwm = ./services/hardware/amdgpu-pwm.nix;
|
amdgpu-pwm = ./services/hardware/amdgpu-pwm.nix;
|
||||||
betanin = ./services/web-apps/betanin.nix;
|
betanin = ./services/web-apps/betanin.nix;
|
||||||
dunst = ./services/x11/dunst.nix;
|
dunst = ./services/x11/dunst.nix;
|
||||||
porkbun-ddns = ./services/networking/porkbun-ddns.nix;
|
|
||||||
radeon-profile-daemon = ./services/hardware/radeon-profile-daemon.nix;
|
radeon-profile-daemon = ./services/hardware/radeon-profile-daemon.nix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkOption types;
|
|
||||||
|
|
||||||
cfg = config.services.porkbun-ddns;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
services.porkbun-ddns = {
|
|
||||||
enable = lib.mkEnableOption "Porkbun dynamic DNS client";
|
|
||||||
|
|
||||||
package = mkOption {
|
|
||||||
# TODO: How do I use mkPackageOption when the package isn't in the
|
|
||||||
# package set?
|
|
||||||
type = types.package;
|
|
||||||
default = pkgs.callPackage ../../../pkgs/by-name/po/porkbun-ddns/package.nix { };
|
|
||||||
defaultText = "pkgs.porkbun-ddns";
|
|
||||||
description = lib.mdDoc "The porkbun-ddns package to use.";
|
|
||||||
};
|
|
||||||
|
|
||||||
interval = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "10m";
|
|
||||||
description = lib.mdDoc ''
|
|
||||||
Interval to update dynamic DNS records. The default is to update every
|
|
||||||
10 minutes. The format is described in {manpage}`systemd.time(7)`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
domains = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
description = lib.mdDoc "Domains to update.";
|
|
||||||
};
|
|
||||||
|
|
||||||
apiKeyFile = mkOption {
|
|
||||||
type = types.nullOr types.path;
|
|
||||||
description = lib.mdDoc ''
|
|
||||||
File containing the API key to use when running the client.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
secretApiKeyFile = mkOption {
|
|
||||||
type = types.nullOr types.path;
|
|
||||||
description = lib.mdDoc ''
|
|
||||||
File containing the secret API key to use when running the
|
|
||||||
client.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
systemd.services.porkbun-ddns = {
|
|
||||||
description = "Porkbun dynamic DNS client";
|
|
||||||
script = ''
|
|
||||||
${cfg.package}/bin/porkbun-ddns \
|
|
||||||
-K ${cfg.apiKeyFile} \
|
|
||||||
-S ${cfg.secretApiKeyFile} \
|
|
||||||
${lib.concatStringsSep " " cfg.domains}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.timers.porkbun-ddns = {
|
|
||||||
description = "Porkbun dynamic DNS client";
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
wantedBy = [ "timers.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnBootSec = cfg.interval;
|
|
||||||
OnUnitActiveSec = cfg.interval;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -9,11 +9,11 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "atlauncher";
|
pname = "atlauncher";
|
||||||
version = "3.4.35.2";
|
version = "3.4.34.0";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/ATLauncher/ATLauncher/releases/download/v${version}/ATLauncher-${version}.jar";
|
url = "https://github.com/ATLauncher/ATLauncher/releases/download/v${version}/ATLauncher-${version}.jar";
|
||||||
hash = "sha256-CVJQGMnETW9BOn2To09/UuLrseNfovUyEFhcz/zyHOQ=";
|
hash = "sha256-gHUYZaxADchikoCmAfqFjVbMYhhiwg2BZKctmww1Mlw=";
|
||||||
};
|
};
|
||||||
|
|
||||||
dontUnpack = true;
|
dontUnpack = true;
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
{ lib
|
|
||||||
, stdenv
|
|
||||||
, python3
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
python = python3.withPackages (py: [ py.requests ]);
|
|
||||||
in
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
name = "porkbun-ddns";
|
|
||||||
|
|
||||||
src = ./.;
|
|
||||||
inherit python;
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
install -Dm0755 $src/porkbun-ddns.py $out/bin/porkbun-ddns
|
|
||||||
substituteAllInPlace $out/bin/porkbun-ddns
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "Porkbun dynamic DNS script";
|
|
||||||
license = lib.licenses.gpl3;
|
|
||||||
platforms = python.meta.platforms;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
#!@python@/bin/python
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import requests
|
|
||||||
from dataclasses import dataclass, fields as datafields
|
|
||||||
from enum import Enum, unique
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
APIBASE = "https://porkbun.com/api/json/v3/dns"
|
|
||||||
|
|
||||||
|
|
||||||
def dataclass_from_dict(klass: object, d: dict):
|
|
||||||
try:
|
|
||||||
fieldtypes = {f.name: f.type for f in datafields(klass)}
|
|
||||||
return klass(**{f: dataclass_from_dict(fieldtypes[f], d[f]) for f in d})
|
|
||||||
except:
|
|
||||||
return d # Not a dataclass field
|
|
||||||
|
|
||||||
|
|
||||||
def remove_domain(domain: str, name: str):
|
|
||||||
return re.sub(f"\\.?{domain}$", "", name)
|
|
||||||
|
|
||||||
|
|
||||||
@unique
|
|
||||||
class RecordType(Enum):
|
|
||||||
a = "A"
|
|
||||||
aaaa = "AAAA"
|
|
||||||
cname = "CNAME"
|
|
||||||
mx = "MX"
|
|
||||||
srv = "SRV"
|
|
||||||
txt = "TXT"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Record:
|
|
||||||
id: str
|
|
||||||
name: str
|
|
||||||
type: str
|
|
||||||
content: str
|
|
||||||
ttl: str
|
|
||||||
prio: str = ""
|
|
||||||
notes: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Retrieval:
|
|
||||||
status: str
|
|
||||||
records: List[Record]
|
|
||||||
|
|
||||||
|
|
||||||
class ApiError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ArgumentError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PorkbunClient:
|
|
||||||
def __init__(self, apikey: str, secretapikey: str):
|
|
||||||
self.apikey = apikey
|
|
||||||
self.secretapikey = secretapikey
|
|
||||||
|
|
||||||
def _make_payload(self, **kwargs):
|
|
||||||
return json.dumps(
|
|
||||||
{"apikey": self.apikey, "secretapikey": self.secretapikey, **kwargs}
|
|
||||||
)
|
|
||||||
|
|
||||||
def edit_record(
|
|
||||||
self,
|
|
||||||
domain: str,
|
|
||||||
record: Record,
|
|
||||||
name: Optional[str] = None,
|
|
||||||
type: Optional[RecordType] = None,
|
|
||||||
content: Optional[str] = None,
|
|
||||||
ttl: Optional[int] = None,
|
|
||||||
priority: Optional[str] = None,
|
|
||||||
) -> bool:
|
|
||||||
return self.edit(
|
|
||||||
domain,
|
|
||||||
record.id,
|
|
||||||
name=name or record.name,
|
|
||||||
type=type or RecordType(record.type),
|
|
||||||
content=content or record.content,
|
|
||||||
ttl=ttl or record.ttl,
|
|
||||||
priority=priority or record.prio,
|
|
||||||
)
|
|
||||||
|
|
||||||
def edit(
|
|
||||||
self,
|
|
||||||
domain: str,
|
|
||||||
id: str,
|
|
||||||
name: str,
|
|
||||||
type: RecordType,
|
|
||||||
content: str,
|
|
||||||
ttl: int = 300,
|
|
||||||
priority: Optional[str] = None,
|
|
||||||
) -> bool:
|
|
||||||
# API returns FQN name rather than the actual prefix, so scrub it
|
|
||||||
name = remove_domain(domain, name)
|
|
||||||
payload = self._make_payload(
|
|
||||||
name=name, type=type.value, content=content, ttl=str(ttl), prio=priority
|
|
||||||
)
|
|
||||||
res = requests.post(f"{APIBASE}/edit/{domain}/{id}", data=payload)
|
|
||||||
body = res.json()
|
|
||||||
if body["status"] != "SUCCESS":
|
|
||||||
raise ApiError(body["message"])
|
|
||||||
return True
|
|
||||||
|
|
||||||
def delete(self, domain: str, id: str) -> bool:
|
|
||||||
payload = self._make_payload()
|
|
||||||
res = requests.post(f"{APIBASE}/delete/{domain}/{id}", data=payload)
|
|
||||||
body = res.json()
|
|
||||||
if body["status"] != "SUCCESS":
|
|
||||||
raise ApiError(body["message"])
|
|
||||||
return True
|
|
||||||
|
|
||||||
def retrieve(self, domain: str) -> List[Retrieval]:
|
|
||||||
payload = self._make_payload()
|
|
||||||
res = requests.post(f"{APIBASE}/retrieve/{domain}", data=payload)
|
|
||||||
body = res.json()
|
|
||||||
if body["status"] != "SUCCESS":
|
|
||||||
raise ApiError(body["message"])
|
|
||||||
return [dataclass_from_dict(Record, d) for d in body["records"]]
|
|
||||||
|
|
||||||
|
|
||||||
def current_ip() -> str:
|
|
||||||
return requests.get("https://ifconfig.me").text
|
|
||||||
|
|
||||||
|
|
||||||
def _load_key(key: Optional[str], keyfile: Optional[str]) -> str:
|
|
||||||
if keyfile is not None:
|
|
||||||
with open(keyfile) as f:
|
|
||||||
return f.read().strip()
|
|
||||||
if key is not None:
|
|
||||||
return key
|
|
||||||
raise ArgumentError("key or key file is required")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = argparse.ArgumentParser(description="Wrapper around Porkbun DNS API")
|
|
||||||
keyarg = parser.add_mutually_exclusive_group(required=True)
|
|
||||||
keyarg.add_argument("-k", "--key", metavar="KEY", type=str, help="API key")
|
|
||||||
keyarg.add_argument(
|
|
||||||
"-K", "--key-file", metavar="FILE", type=str, help="API key file"
|
|
||||||
)
|
|
||||||
secretarg = parser.add_mutually_exclusive_group(required=True)
|
|
||||||
secretarg.add_argument(
|
|
||||||
"-s", "--secret", metavar="SECRET", type=str, help="secret API key"
|
|
||||||
)
|
|
||||||
secretarg.add_argument(
|
|
||||||
"-S", "--secret-file", metavar="FILE", type=str, help="secret API key file"
|
|
||||||
)
|
|
||||||
parser.add_argument("domains", type=str, nargs="+", help="domain(s) to update")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
try:
|
|
||||||
apikey = _load_key(args.key, args.key_file)
|
|
||||||
secretapikey = _load_key(args.secret, args.secret_file)
|
|
||||||
except Exception as e:
|
|
||||||
print("error: " + str(e))
|
|
||||||
parser.print_help()
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
current_ip = current_ip()
|
|
||||||
client = PorkbunClient(apikey, secretapikey)
|
|
||||||
for domain in args.domains:
|
|
||||||
recs = client.retrieve(domain)
|
|
||||||
arecs = [r for r in recs if r.type == RecordType.a.value]
|
|
||||||
for arec in arecs:
|
|
||||||
if arec.content != current_ip:
|
|
||||||
client.edit_record(domain, arec, content=current_ip)
|
|
||||||
print(f"Pointed '{arec.name}' to {current_ip}")
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
{ lib
|
|
||||||
, stdenvNoCC
|
|
||||||
, fetchFromGitHub
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
mkMonaspace =
|
|
||||||
{ pname
|
|
||||||
, variants ? [ ]
|
|
||||||
}: stdenvNoCC.mkDerivation rec {
|
|
||||||
inherit pname;
|
|
||||||
version = "1.000";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "githubnext";
|
|
||||||
repo = "monaspace";
|
|
||||||
rev = "v${version}";
|
|
||||||
hash = "sha256-Zo56r0QoLwxwGQtcWP5cDlasx000G9BFeGINvvwEpQs=";
|
|
||||||
};
|
|
||||||
|
|
||||||
_variants = map (builtins.replaceStrings [ " " ] [ "" ]) variants;
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
local out_font=$out/share/fonts/monaspace
|
|
||||||
'' + (if variants == [ ] then ''
|
|
||||||
install -m444 -Dt $out_font fonts/otf/*.otf
|
|
||||||
install -m444 -Dt $out_font fonts/variable/*.ttf
|
|
||||||
'' else ''
|
|
||||||
for variant in $_variants; do
|
|
||||||
install -m444 -Dt $out_font fonts/otf/"$variant"-*.otf
|
|
||||||
install -m444 -Dt $out_font fonts/variable/"$variant"Var*.ttf
|
|
||||||
done
|
|
||||||
'');
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "An innovative superfamily of fonts for code";
|
|
||||||
homepage = "https://monaspace.githubnext.com/";
|
|
||||||
longDescription = ''
|
|
||||||
Since the earliest days of the teletype machine, code has been set in
|
|
||||||
monospaced type — letters, on a grid. Monaspace is a new type system
|
|
||||||
that advances the state of the art for the display of code on screen.
|
|
||||||
'';
|
|
||||||
license = lib.licenses.ofl;
|
|
||||||
platforms = lib.platforms.all;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
monaspace = mkMonaspace {
|
|
||||||
pname = "monaspace";
|
|
||||||
};
|
|
||||||
|
|
||||||
monaspace-argon = mkMonaspace {
|
|
||||||
pname = "monaspace-argon";
|
|
||||||
variants = [ "Monaspace Argon" ];
|
|
||||||
};
|
|
||||||
monaspace-krypton = mkMonaspace {
|
|
||||||
pname = "monaspace-krypton";
|
|
||||||
variants = [ "Monaspace Krypton" ];
|
|
||||||
};
|
|
||||||
monaspace-neon = mkMonaspace {
|
|
||||||
pname = "monaspace-neon";
|
|
||||||
variants = [ "Monaspace Neon" ];
|
|
||||||
};
|
|
||||||
monaspace-radon = mkMonaspace {
|
|
||||||
pname = "monaspace-radon";
|
|
||||||
variants = [ "Monaspace Radon" ];
|
|
||||||
};
|
|
||||||
monaspace-xenon = mkMonaspace {
|
|
||||||
pname = "monaspace-xenon";
|
|
||||||
variants = [ "Monaspace Xenon" ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -21,15 +21,6 @@ rec {
|
|||||||
ideaUltimateWithPlugins = ideaUltimatePlugins.jetbrainsWithPlugins;
|
ideaUltimateWithPlugins = ideaUltimatePlugins.jetbrainsWithPlugins;
|
||||||
};
|
};
|
||||||
|
|
||||||
monaspace-fonts = pkgs.callPackage ../data/fonts/monaspace/default.nix { };
|
|
||||||
inherit (monaspace-fonts)
|
|
||||||
monaspace
|
|
||||||
monaspace-argon
|
|
||||||
monaspace-krypton
|
|
||||||
monaspace-neon
|
|
||||||
monaspace-radon
|
|
||||||
monaspace-xenon;
|
|
||||||
|
|
||||||
mopidy-subidy = pkgs.callPackage ../applications/audio/mopidy/subidy.nix {
|
mopidy-subidy = pkgs.callPackage ../applications/audio/mopidy/subidy.nix {
|
||||||
python3Packages = pkgs.python3Packages // python3Packages;
|
python3Packages = pkgs.python3Packages // python3Packages;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user