Runner updated and eurovote
This commit is contained in:
Generated
+21
@@ -1,5 +1,25 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"eurovote": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1778959671,
|
||||||
|
"narHash": "sha256-MR70Q1lNOX7lqO7PwQUtJdB4+exZr8R10YPQanc5SwE=",
|
||||||
|
"owner": "anerisgreat",
|
||||||
|
"repo": "eurovote",
|
||||||
|
"rev": "245d9b1f3e182653e5cfa0d9689a97f263eb4354",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "anerisgreat",
|
||||||
|
"repo": "eurovote",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixos-hardware": {
|
"nixos-hardware": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1776983936,
|
"lastModified": 1776983936,
|
||||||
@@ -34,6 +54,7 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"eurovote": "eurovote",
|
||||||
"nixos-hardware": "nixos-hardware",
|
"nixos-hardware": "nixos-hardware",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"sops-nix": "sops-nix"
|
"sops-nix": "sops-nix"
|
||||||
|
|||||||
@@ -14,9 +14,15 @@
|
|||||||
# We use only the minimal pieces needed for a headless server —
|
# We use only the minimal pieces needed for a headless server —
|
||||||
# no display, audio, or bluetooth modules.
|
# no display, audio, or bluetooth modules.
|
||||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||||
|
|
||||||
|
# Eurovision voting app
|
||||||
|
eurovote = {
|
||||||
|
url = "github:anerisgreat/eurovote";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, sops-nix, nixos-hardware, ... }@inputs:
|
outputs = { self, nixpkgs, sops-nix, nixos-hardware, eurovote, ... }@inputs:
|
||||||
let
|
let
|
||||||
# Shared specialArgs passed to every host
|
# Shared specialArgs passed to every host
|
||||||
commonArgs = {
|
commonArgs = {
|
||||||
@@ -74,6 +80,8 @@
|
|||||||
./modules/services/uptime-kuma.nix
|
./modules/services/uptime-kuma.nix
|
||||||
./modules/services/ntfy.nix
|
./modules/services/ntfy.nix
|
||||||
./modules/monitoring.nix
|
./modules/monitoring.nix
|
||||||
|
eurovote.nixosModules.default
|
||||||
|
./modules/services/eurovote.nix
|
||||||
] ++ extraModules;
|
] ++ extraModules;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,9 @@
|
|||||||
# CI/CD
|
# CI/CD
|
||||||
homey.giteaRunner.enable = true;
|
homey.giteaRunner.enable = true;
|
||||||
|
|
||||||
|
# Eurovision voting app
|
||||||
|
homey.eurovote.enable = true;
|
||||||
|
|
||||||
# Monitoring stack
|
# Monitoring stack
|
||||||
homey.uptimeKuma.enable = true;
|
homey.uptimeKuma.enable = true;
|
||||||
homey.ntfy.enable = true;
|
homey.ntfy.enable = true;
|
||||||
@@ -186,7 +189,17 @@
|
|||||||
|
|
||||||
# hdparm -B udev rule removed: USB-SATA bridges often don't support APM
|
# hdparm -B udev rule removed: USB-SATA bridges often don't support APM
|
||||||
# commands and hdparm can hang indefinitely, causing boot-time crashes.
|
# commands and hdparm can hang indefinitely, causing boot-time crashes.
|
||||||
environment.systemPackages = [ pkgs.hdparm ];
|
environment.systemPackages = [ pkgs.hdparm pkgs.tmux ];
|
||||||
|
|
||||||
|
systemd.services.nextcloud-generate-previews = {
|
||||||
|
description = "Generate missing Nextcloud preview thumbnails";
|
||||||
|
after = [ "podman-nextcloud.service" ];
|
||||||
|
requires = [ "podman-nextcloud.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${pkgs.podman}/bin/podman exec -u www-data nextcloud php occ preview:generate-all";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Local DNS overrides (optional — makes LAN clients hit the Pi directly
|
# Local DNS overrides (optional — makes LAN clients hit the Pi directly
|
||||||
|
|||||||
@@ -139,12 +139,15 @@ in
|
|||||||
# Monitoring — uptime-kuma has monitors/history, ntfy has user accounts
|
# Monitoring — uptime-kuma has monitors/history, ntfy has user accounts
|
||||||
"${dataDir}/uptime-kuma"
|
"${dataDir}/uptime-kuma"
|
||||||
"${dataDir}/ntfy"
|
"${dataDir}/ntfy"
|
||||||
|
# Eurovision Vote — SQLite DB with votes and rankings
|
||||||
|
"/var/lib/eurovote"
|
||||||
];
|
];
|
||||||
|
|
||||||
# Exclude Nextcloud's raw DB directory in favour of the pg_dump file
|
# Exclude Nextcloud's raw DB directory in favour of the pg_dump file
|
||||||
exclude = [
|
exclude = [
|
||||||
"${dataDir}/nextcloud/db"
|
"${dataDir}/nextcloud/db"
|
||||||
"${dataDir}/restic-cache"
|
"${dataDir}/restic-cache"
|
||||||
|
"${dataDir}/media"
|
||||||
];
|
];
|
||||||
|
|
||||||
timerConfig = {
|
timerConfig = {
|
||||||
|
|||||||
+27
-6
@@ -42,19 +42,16 @@ let
|
|||||||
|
|
||||||
# Reusable Authelia forward_auth snippet
|
# Reusable Authelia forward_auth snippet
|
||||||
# Returns a Caddyfile snippet block that applies forward_auth.
|
# Returns a Caddyfile snippet block that applies forward_auth.
|
||||||
|
# Uses the v4.38+ /api/authz/forward-auth endpoint which correctly honours
|
||||||
|
# one_factor policy without forcing TOTP enrollment on new users.
|
||||||
# copy_headers makes Authelia's Remote-* headers available downstream.
|
# copy_headers makes Authelia's Remote-* headers available downstream.
|
||||||
autheliaForwardAuth = ''
|
autheliaForwardAuth = ''
|
||||||
forward_auth localhost:9091 {
|
forward_auth localhost:9091 {
|
||||||
uri /api/verify?rd=https://auth.${domain}
|
uri /api/authz/forward-auth?authelia_url=https://auth.${domain}
|
||||||
copy_headers Remote-User Remote-Name Remote-Groups Remote-Email
|
copy_headers Remote-User Remote-Name Remote-Groups Remote-Email
|
||||||
# Always tell Authelia the scheme is https (cloudflared terminates TLS
|
# Always tell Authelia the scheme is https (cloudflared terminates TLS
|
||||||
# externally; Caddy's http:// vhosts are only for the tunnel loopback).
|
# externally; Caddy's http:// vhosts are only for the tunnel loopback).
|
||||||
header_up X-Forwarded-Proto https
|
header_up X-Forwarded-Proto https
|
||||||
# On auth failure, redirect to the authelia login page
|
|
||||||
@goauth status 401
|
|
||||||
handle_response @goauth {
|
|
||||||
redir https://auth.${domain}?rm={method} 302
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@@ -236,6 +233,30 @@ in
|
|||||||
extraConfig = cfProxy 2586;
|
extraConfig = cfProxy 2586;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Eurovision Vote — one_factor for all authenticated users.
|
||||||
|
# /admin/* is restricted to group:admins by Authelia access_control.
|
||||||
|
# Caddy passes Remote-User → X-Remote-User so Django auto-logs in
|
||||||
|
# the SSO-authenticated user via RemoteUserMiddleware.
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
"eurovision-vote.${domain}" = {
|
||||||
|
extraConfig = ''
|
||||||
|
${autheliaForwardAuth}
|
||||||
|
reverse_proxy localhost:8007 {
|
||||||
|
header_up X-Remote-User {http.request.header.Remote-User}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
"http://eurovision-vote.${domain}" = {
|
||||||
|
extraConfig = ''
|
||||||
|
${autheliaForwardAuth}
|
||||||
|
reverse_proxy localhost:8007 {
|
||||||
|
header_up X-Forwarded-Proto https
|
||||||
|
header_up X-Remote-User {http.request.header.Remote-User}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Grafana — two_factor, admins only (enforced by authelia policy).
|
# Grafana — two_factor, admins only (enforced by authelia policy).
|
||||||
# After Authelia verifies the user, Caddy maps the Remote-User header
|
# After Authelia verifies the user, Caddy maps the Remote-User header
|
||||||
|
|||||||
@@ -26,6 +26,9 @@
|
|||||||
# between weekly GC runs.
|
# between weekly GC runs.
|
||||||
min-free = 2147483648; # 2 GiB
|
min-free = 2147483648; # 2 GiB
|
||||||
max-free = 5368709120; # 5 GiB
|
max-free = 5368709120; # 5 GiB
|
||||||
|
# Use the external drive for sandbox builds — the default /tmp is a
|
||||||
|
# small RAM-backed tmpfs that fills up during large builds (e.g. wrangler).
|
||||||
|
build-dir = "/mnt/data/nix-build";
|
||||||
};
|
};
|
||||||
gc = {
|
gc = {
|
||||||
automatic = true;
|
automatic = true;
|
||||||
@@ -37,6 +40,10 @@
|
|||||||
# Allow unfree packages (e.g. cloudflared binary)
|
# Allow unfree packages (e.g. cloudflared binary)
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /mnt/data/nix-build 0755 root root -"
|
||||||
|
];
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Boot — set in hardware.nix; this is just a safe default
|
# Boot — set in hardware.nix; this is just a safe default
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -128,6 +128,22 @@ let
|
|||||||
- domain:
|
- domain:
|
||||||
- "ntfy.${domain}"
|
- "ntfy.${domain}"
|
||||||
policy: "bypass"
|
policy: "bypass"
|
||||||
|
# Eurovision Vote: /admin/* for admins only; all others one_factor
|
||||||
|
- domain:
|
||||||
|
- "eurovision-vote.${domain}"
|
||||||
|
resources:
|
||||||
|
- "^/admin.*$"
|
||||||
|
subject:
|
||||||
|
- "group:admins"
|
||||||
|
policy: "two_factor"
|
||||||
|
- domain:
|
||||||
|
- "eurovision-vote.${domain}"
|
||||||
|
resources:
|
||||||
|
- "^/admin.*$"
|
||||||
|
policy: "deny"
|
||||||
|
- domain:
|
||||||
|
- "eurovision-vote.${domain}"
|
||||||
|
policy: "one_factor"
|
||||||
|
|
||||||
notifier:
|
notifier:
|
||||||
filesystem:
|
filesystem:
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{ config, lib, pkgs, homeyConfig, ... }:
|
||||||
|
|
||||||
|
# Eurovision Vote — Django app for ranking Eurovision performances.
|
||||||
|
#
|
||||||
|
# Uses the NixOS module from the eurovote flake (eurovote.nixosModules.default).
|
||||||
|
# This wrapper wires it into the homey module system: enable flag, sops secret,
|
||||||
|
# and uptime monitoring.
|
||||||
|
#
|
||||||
|
# The app uses DynamicUser + StateDirectory so systemd owns /var/lib/eurovote/;
|
||||||
|
# no tmpfiles.rules entry needed.
|
||||||
|
#
|
||||||
|
# Authentication: Caddy forward_auth → Authelia; the app reads the
|
||||||
|
# X-Remote-User header set by Caddy (from Authelia's Remote-User).
|
||||||
|
# All authenticated users get app access; /admin/* is restricted to
|
||||||
|
# group:admins by Authelia's access_control rules (see authelia.nix).
|
||||||
|
#
|
||||||
|
# Secrets consumed from sops:
|
||||||
|
# eurovote/secret_key
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.homey.eurovote;
|
||||||
|
domain = homeyConfig.domain;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.homey.eurovote = {
|
||||||
|
enable = lib.mkEnableOption "Eurovision Vote app";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Secrets
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# mode 0444: the service runs as a DynamicUser (random UID) so it cannot
|
||||||
|
# read a root-owned 0400 file. /run/secrets/ itself is not world-listable
|
||||||
|
# (mode 0751), so world-readable here is acceptable on a home server.
|
||||||
|
sops.secrets."eurovote/secret_key" = { owner = "root"; mode = "0444"; };
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Service (options provided by eurovote.nixosModules.default)
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
services.eurovote = {
|
||||||
|
enable = true;
|
||||||
|
port = 8007;
|
||||||
|
allowedHosts = "localhost 127.0.0.1 eurovision-vote.${domain}";
|
||||||
|
secretKeyFile = config.sops.secrets."eurovote/secret_key".path;
|
||||||
|
trustedOrigins = "https://eurovision-vote.${domain}";
|
||||||
|
# After SSO logout, send the user back to Authelia's logout page
|
||||||
|
logoutRedirectUrl = "https://auth.${domain}/logout";
|
||||||
|
};
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Uptime Kuma monitor
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
homey.monitoring.monitors = [{
|
||||||
|
name = "Eurovision Vote";
|
||||||
|
url = "https://eurovision-vote.${domain}";
|
||||||
|
interval = 60;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
# nested containers on a Pi 4.
|
# nested containers on a Pi 4.
|
||||||
#
|
#
|
||||||
# The service uses DynamicUser=true so there is no persistent system user.
|
# The service uses DynamicUser=true so there is no persistent system user.
|
||||||
# nix/git/bash are available in jobs via the system PATH inherited from the
|
# Job step PATH is controlled by hostPackages (not the service PATH).
|
||||||
# service environment.
|
# nix is not in the NixOS module's default hostPackages and must be added.
|
||||||
#
|
#
|
||||||
# Setup (one-time):
|
# Setup (one-time):
|
||||||
# 1. In Gitea: Site Administration → Actions → Runners → Create Runner Token
|
# 1. In Gitea: Site Administration → Actions → Runners → Create Runner Token
|
||||||
@@ -61,8 +61,12 @@ in
|
|||||||
tokenFile = config.sops.secrets."gitea/runner_token".path;
|
tokenFile = config.sops.secrets."gitea/runner_token".path;
|
||||||
name = cfg.name;
|
name = cfg.name;
|
||||||
labels = cfg.labels;
|
labels = cfg.labels;
|
||||||
# nix/git/bash are accessible via the system PATH (/run/current-system/sw/bin/)
|
# hostPackages controls the PATH available to job steps (host executor).
|
||||||
# without any extra configuration — the runner inherits it as a system user.
|
# nix is not in the default list so must be added explicitly.
|
||||||
|
hostPackages = with pkgs; [
|
||||||
|
bash coreutils curl gawk gitMinimal gnused nodejs wget
|
||||||
|
nix
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,11 +130,6 @@ let
|
|||||||
api.disconnect()
|
api.disconnect()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Collect all configured notification IDs so every monitor gets them.
|
|
||||||
notification_ids = [n["id"] for n in api.get_notifications()]
|
|
||||||
if notification_ids:
|
|
||||||
print(f"uptime-kuma-sync: attaching notifications: {notification_ids}")
|
|
||||||
|
|
||||||
# Sync monitors: add missing, update changed
|
# Sync monitors: add missing, update changed
|
||||||
try:
|
try:
|
||||||
existing = {m["name"]: m for m in api.get_monitors()}
|
existing = {m["name"]: m for m in api.get_monitors()}
|
||||||
@@ -150,7 +145,6 @@ let
|
|||||||
url=m["url"],
|
url=m["url"],
|
||||||
interval=m.get("interval", 60),
|
interval=m.get("interval", 60),
|
||||||
maxretries=maxretries,
|
maxretries=maxretries,
|
||||||
notification_id_list={str(nid): True for nid in notification_ids},
|
|
||||||
**extra,
|
**extra,
|
||||||
)
|
)
|
||||||
print(f"uptime-kuma-sync: created monitor: {m['name']}")
|
print(f"uptime-kuma-sync: created monitor: {m['name']}")
|
||||||
@@ -163,7 +157,6 @@ let
|
|||||||
url=m["url"],
|
url=m["url"],
|
||||||
interval=m.get("interval", 60),
|
interval=m.get("interval", 60),
|
||||||
maxretries=maxretries,
|
maxretries=maxretries,
|
||||||
notification_id_list={str(nid): True for nid in notification_ids},
|
|
||||||
**extra,
|
**extra,
|
||||||
)
|
)
|
||||||
print(f"uptime-kuma-sync: updated monitor: {m['name']}")
|
print(f"uptime-kuma-sync: updated monitor: {m['name']}")
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ restic:
|
|||||||
s3_secret_access_key: ENC[AES256_GCM,data:9ZWyhGJm4t2benDrLmnyQ9ZA5Jjl6l+pza1VmymTlw==,iv:xYsG6QlxXhQNO9szmsycxP6lT0cFF7lq3iNg6j+ED0E=,tag:wOJT4Vg3DuNFWTtx3QS9IQ==,type:str]
|
s3_secret_access_key: ENC[AES256_GCM,data:9ZWyhGJm4t2benDrLmnyQ9ZA5Jjl6l+pza1VmymTlw==,iv:xYsG6QlxXhQNO9szmsycxP6lT0cFF7lq3iNg6j+ED0E=,tag:wOJT4Vg3DuNFWTtx3QS9IQ==,type:str]
|
||||||
wifi:
|
wifi:
|
||||||
psk: ENC[AES256_GCM,data:znk9Wr+vsntzbJ3H0TORUrAiDw==,iv:wbl8fUuKlgTqhajwjlTgFS7ijaTwXBFPRW2AmtiTklg=,tag:IK4oe8cJcccPaQ0V0NlncQ==,type:str]
|
psk: ENC[AES256_GCM,data:znk9Wr+vsntzbJ3H0TORUrAiDw==,iv:wbl8fUuKlgTqhajwjlTgFS7ijaTwXBFPRW2AmtiTklg=,tag:IK4oe8cJcccPaQ0V0NlncQ==,type:str]
|
||||||
|
eurovote:
|
||||||
|
secret_key: ENC[AES256_GCM,data:Re9MTYA46ERXsxucT19K4Pj3rV5i74s8zQ/WYj6GlxeoN1r0Oit6PP0C3PY5Arp6Y6g=,iv:0BnuZ9Uv2RgDwlisrVSvg7ESmNZvd8trggQDSJ42ewM=,tag:SXW2hbprj2qSRzjKY3Aw3Q==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age120j8ty7nn04l3s3kgph5ty3v9g4e52fknn8xtnmzwakq9nv2la3skgte0p
|
- recipient: age120j8ty7nn04l3s3kgph5ty3v9g4e52fknn8xtnmzwakq9nv2la3skgte0p
|
||||||
@@ -42,8 +44,8 @@ sops:
|
|||||||
QXVkRlJHeW52NFZFYnVwaW8ycytDSzAKZt+p5QnZKcEOBghHA2xkH6d7NObtTEoE
|
QXVkRlJHeW52NFZFYnVwaW8ycytDSzAKZt+p5QnZKcEOBghHA2xkH6d7NObtTEoE
|
||||||
wMwCYasnBHzy2unXRbZq/4v9NQ5HJd0Nu1iqbqKgIxMCD3dnxEdK7g==
|
wMwCYasnBHzy2unXRbZq/4v9NQ5HJd0Nu1iqbqKgIxMCD3dnxEdK7g==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2026-05-10T20:36:03Z"
|
lastmodified: "2026-05-13T20:49:38Z"
|
||||||
mac: ENC[AES256_GCM,data:aEC9pHnupssTzcw9HdtqkzzhsNkkJMYT3qiwKPLCcIfDMN1Lv3Msi0TJyFjqjR/vzOfAyHFgsPjSWFladL7fOZHpqq2VeNYHPF9/GKEuoEMqsISN2FczqrTHNC8aI/vhZxe3BxgkX9neiHR9v31MRpX9lq6AbCrEJ42hCh6rCxs=,iv:41Dx92loo4zgKt+7iqjgaOZZUe58VAGEGgOEHEuztzQ=,tag:Oagh8hxWfXWuNI70WHULYA==,type:str]
|
mac: ENC[AES256_GCM,data:2iQyp3U5KYCHIWvBsEyz8XFLTtQ5dN+2TF1gkFADFCyyJLAPWAxYPSH60d7fhJ5qhs7IJ7GV/N1J23JsXV+jyqS95foF9ThYT/wNeh4cAPGWB5RbnpP9RsYt8nCEIl/RHkkGmnS9HUO2HHpqo7hMUGRCHMLYMxJxHdPGrm+KHgA=,iv:D+x06308n14/xkRR9WvD6MYcORVM+crIH20+oHesHds=,tag:q7L7OyXEXThYFEkPrgzSBw==,type:str]
|
||||||
pgp:
|
pgp:
|
||||||
- created_at: "2026-04-21T06:39:49Z"
|
- created_at: "2026-04-21T06:39:49Z"
|
||||||
enc: |-
|
enc: |-
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
alejandra
|
alejandra
|
||||||
|
sops
|
||||||
(pkgs.writeShellScriptBin "homey-deploy-rpi-main" ''
|
(pkgs.writeShellScriptBin "homey-deploy-rpi-main" ''
|
||||||
nixos-rebuild switch \
|
nixos-rebuild switch \
|
||||||
--flake .#pi-main \
|
--flake .#pi-main \
|
||||||
|
|||||||
Reference in New Issue
Block a user