Compare commits
7 commits
f606662818
...
327f2452c5
Author | SHA1 | Date | |
---|---|---|---|
327f2452c5 | |||
113a602bb4 | |||
488f089a3a | |||
6993dc5b6f | |||
29132575ff | |||
262e185eb1 | |||
e8526a1c82 |
27 changed files with 609 additions and 61 deletions
218
flake.lock
218
flake.lock
|
@ -23,23 +23,24 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"bootspec-secureboot": {
|
||||
"crane": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"lanzaboote",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1732935682,
|
||||
"narHash": "sha256-KKIeqAesU1RFqJR4cETK75gjeCMXhw1WJ8xLAwLJ1uA=",
|
||||
"owner": "vikanezrimaya",
|
||||
"repo": "bootspec-secureboot",
|
||||
"rev": "c63227f62c8b6af753e8ca2533fee13408dfaa5c",
|
||||
"lastModified": 1717535930,
|
||||
"narHash": "sha256-1hZ/txnbd/RmiBPNUs7i8UQw2N89uAK3UzrGAWdnFfU=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "55e7754ec31dac78980c8be45f8a28e80e370946",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "vikanezrimaya",
|
||||
"repo": "bootspec-secureboot",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
@ -51,17 +52,17 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722725362,
|
||||
"narHash": "sha256-JKonFnKwiN7VRXhn3pUhoN6TGDoyHepWbMfVd35wTew=",
|
||||
"lastModified": 1736029622,
|
||||
"narHash": "sha256-4+LgwpKEgSztPFzKIKwJrOH/4FTCsLCkWGc7LhXPcSY=",
|
||||
"owner": "teidesu",
|
||||
"repo": "desu-deploy",
|
||||
"rev": "a77b8e790324df51471cf40924acff9643972dfa",
|
||||
"rev": "d373e8ab554a95d222e3ced87e751dabbd3cfc57",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "teidesu",
|
||||
"repo": "desu-deploy",
|
||||
"rev": "a77b8e790324df51471cf40924acff9643972dfa",
|
||||
"rev": "d373e8ab554a95d222e3ced87e751dabbd3cfc57",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
@ -85,6 +86,43 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"lanzaboote",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1717285511,
|
||||
"narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
|
@ -107,6 +145,24 @@
|
|||
"inputs": {
|
||||
"systems": "systems_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_3": {
|
||||
"inputs": {
|
||||
"systems": "systems_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1681202837,
|
||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||
|
@ -121,6 +177,28 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"lanzaboote",
|
||||
"pre-commit-hooks-nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -163,6 +241,33 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"lanzaboote": {
|
||||
"inputs": {
|
||||
"crane": "crane",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-parts": "flake-parts",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1718178907,
|
||||
"narHash": "sha256-eSZyrQ9uoPB9iPQ8Y5H7gAmAgAvCw3InStmU3oEjqsE=",
|
||||
"owner": "nix-community",
|
||||
"repo": "lanzaboote",
|
||||
"rev": "b627ccd97d0159214cee5c7db1412b75e4be6086",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "v0.4.1",
|
||||
"repo": "lanzaboote",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -220,6 +325,22 @@
|
|||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1710695816,
|
||||
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-23.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1720535198,
|
||||
"narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=",
|
||||
|
@ -249,20 +370,72 @@
|
|||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks-nix": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"lanzaboote",
|
||||
"flake-compat"
|
||||
],
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"lanzaboote",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1717664902,
|
||||
"narHash": "sha256-7XfBuLULizXjXfBYy/VV+SpYMHreNRHk9nKMsm1bgb4=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "cc4d466cb1254af050ff7bdf47f6d404a7c646d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"bootspec-secureboot": "bootspec-secureboot",
|
||||
"desu-deploy": "desu-deploy",
|
||||
"disko": "disko",
|
||||
"home-manager": "home-manager_2",
|
||||
"lanzaboote": "lanzaboote",
|
||||
"nix-darwin": "nix-darwin",
|
||||
"nix-index-database": "nix-index-database",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-stable": "nixpkgs-stable",
|
||||
"nixpkgs-stable": "nixpkgs-stable_2",
|
||||
"vscode-server": "vscode-server"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"lanzaboote",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"lanzaboote",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1717813066,
|
||||
"narHash": "sha256-wqbRwq3i7g5EHIui0bIi84mdqZ/It1AXBSLJ5tafD28=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "6dc3e45fe4aee36efeed24d64fc68b1f989d5465",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
|
@ -308,9 +481,24 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_4": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"vscode-server": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"flake-utils": "flake-utils_3",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
|
|
17
flake.nix
17
flake.nix
|
@ -26,8 +26,8 @@
|
|||
inputs.darwin.follows = "";
|
||||
};
|
||||
|
||||
bootspec-secureboot = {
|
||||
url = "github:vikanezrimaya/bootspec-secureboot";
|
||||
lanzaboote = {
|
||||
url = "github:nix-community/lanzaboote/v0.4.1";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
|||
disko.url = "github:nix-community/disko";
|
||||
disko.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
desu-deploy.url = "github:teidesu/desu-deploy/a77b8e790324df51471cf40924acff9643972dfa";
|
||||
desu-deploy.url = "github:teidesu/desu-deploy/d373e8ab554a95d222e3ced87e751dabbd3cfc57";
|
||||
desu-deploy.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
|||
, nixpkgs-stable
|
||||
, vscode-server
|
||||
, agenix
|
||||
, bootspec-secureboot
|
||||
, lanzaboote
|
||||
, home-manager
|
||||
, nix-darwin
|
||||
, desu-deploy
|
||||
|
@ -108,7 +108,7 @@
|
|||
koi = mkNixosSystem rec {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
bootspec-secureboot.nixosModules.bootspec-secureboot
|
||||
lanzaboote.nixosModules.lanzaboote
|
||||
desu-deploy.nixosModules.${system}.default
|
||||
./hosts/koi/configuration.nix
|
||||
];
|
||||
|
@ -117,14 +117,15 @@
|
|||
homura = mkNixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./hosts/madohomu/homura.nix
|
||||
./hosts/homura/configuration.nix
|
||||
];
|
||||
};
|
||||
|
||||
madoka = mkNixosSystem {
|
||||
madoka = mkNixosSystem rec {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./hosts/madohomu/madoka.nix
|
||||
desu-deploy.nixosModules.${system}.default
|
||||
./hosts/madoka/configuration.nix
|
||||
];
|
||||
};
|
||||
|
||||
|
|
25
hosts/homura/configuration.nix
Normal file
25
hosts/homura/configuration.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
{ modulesPath, abs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/minimal.nix")
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
boot.tmp.cleanOnBoot = true;
|
||||
zramSwap.enable = true;
|
||||
|
||||
age.identityPaths = [
|
||||
"/etc/ssh/agenix_key"
|
||||
];
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keyFiles = [
|
||||
(abs "ssh/teidesu.pub")
|
||||
];
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
|
||||
networking.hostName = "homura";
|
||||
}
|
|
@ -5,5 +5,4 @@ set -eau
|
|||
SCRIPT=$(realpath "$0")
|
||||
SCRIPTPATH=$(dirname "$SCRIPT")
|
||||
|
||||
$SCRIPTPATH/../../switch --remote root@madoka .#madoka
|
||||
$SCRIPTPATH/../../switch --remote root@homura .#homura
|
|
@ -40,6 +40,7 @@
|
|||
./containers/wakapi
|
||||
./containers/outline
|
||||
./containers/docmost
|
||||
./containers/forgejo
|
||||
./containers/teisu.nix
|
||||
./containers/bots/pcre-sub-bot.nix
|
||||
./containers/bots/channel-logger-bot.nix
|
||||
|
|
|
@ -14,13 +14,11 @@ in {
|
|||
|
||||
virtualisation.oci-containers.containers.channel-logger-bot = {
|
||||
image = "ghcr.io/teidesu/channel-logger-bot:latest";
|
||||
environmentFiles = [
|
||||
config.desu.secrets.channel-logger-bot-env.path
|
||||
];
|
||||
environment.MTCUTE_LOG_LEVEL = "5";
|
||||
user = builtins.toString UID;
|
||||
extraOptions = [
|
||||
"--mount=type=bind,source=/srv/channel-logger-bot,target=/app/bot-data"
|
||||
"--mount=type=bind,source=${config.desu.secrets.channel-logger-bot-env.path},target=/app/config.toml"
|
||||
];
|
||||
};
|
||||
|
||||
|
|
48
hosts/koi/containers/forgejo/clear-actions-logs.mjs
Normal file
48
hosts/koi/containers/forgejo/clear-actions-logs.mjs
Normal file
|
@ -0,0 +1,48 @@
|
|||
// forgejo doesn't have a built-in way to clear old actions logs, so we have to do it manually
|
||||
// https://github.com/go-gitea/gitea/issues/24256, didnt find a separate issue for forgejo
|
||||
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
|
||||
const LOGS_DIR = '/srv/forgejo/data/data/actions_log'
|
||||
const RETENTION = 30 * 24 * 60 * 60 * 1000 // 30 days
|
||||
|
||||
function handleLogsDir(dir) {
|
||||
// the actions_log dir structure is something like this:
|
||||
// actions_log/owner/repo/job-id-hex/job-id.log.zst
|
||||
// (todo: verify this is the case)
|
||||
let found = false
|
||||
const subdirs = fs.readdirSync(dir, { withFileTypes: true })
|
||||
for (const subdir of subdirs) {
|
||||
if (!subdir.isDirectory()) continue
|
||||
|
||||
const fullPath = path.join(dir, subdir.name)
|
||||
|
||||
// validate that the structure is how we expect it
|
||||
const jobId = parseInt(subdir.name, 16)
|
||||
if (isNaN(jobId)) {
|
||||
console.error(`invalid job id at: ${fullPath}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const children = fs.readdirSync(fullPath, { withFileTypes: true })
|
||||
if (children.length !== 1 || !children[0].isFile() || children[0].name !== `${jobId}.log.zst`) {
|
||||
console.error(`Invalid actions_log dir: ${dir}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const stat = fs.statSync(fullPath)
|
||||
if (stat.mtimeMs < Date.now() - RETENTION) {
|
||||
console.log(`deleting old (${new Date(stat.mtimeMs).toISOString()}) actions log: ${fullPath}`)
|
||||
fs.rmSync(fullPath, { recursive: true })
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (const owner of fs.readdirSync(LOGS_DIR)) {
|
||||
for (const repo of fs.readdirSync(path.join(LOGS_DIR, owner))) {
|
||||
handleLogsDir(path.join(LOGS_DIR, owner, repo))
|
||||
}
|
||||
}
|
80
hosts/koi/containers/forgejo/default.nix
Normal file
80
hosts/koi/containers/forgejo/default.nix
Normal file
|
@ -0,0 +1,80 @@
|
|||
{ abs, pkgs, config, ... }@inputs:
|
||||
|
||||
let
|
||||
UID = 1125;
|
||||
|
||||
context = pkgs.copyPathToStore ./image;
|
||||
in {
|
||||
users.users.forgejo = {
|
||||
isNormalUser = true;
|
||||
uid = UID;
|
||||
};
|
||||
|
||||
services.postgresql.ensureUsers = [
|
||||
{ name = "forgejo"; ensureDBOwnership = true; }
|
||||
];
|
||||
services.postgresql.ensureDatabases = [ "forgejo" ];
|
||||
desu.postgresql.ensurePasswords.forgejo = "forgejo";
|
||||
|
||||
systemd.services.docker-forgejo.serviceConfig.ExecStartPre = [
|
||||
(pkgs.writeShellScript "build-forgejo" ''
|
||||
docker build -t local/forgejo ${context}
|
||||
'')
|
||||
];
|
||||
virtualisation.oci-containers.containers.forgejo = {
|
||||
image = "local/forgejo";
|
||||
|
||||
# we use a custom entrypoint to set the uid and then drop privileges,
|
||||
# because forgejo expects the running user to have username "git" :woozy:
|
||||
# (and their root image is too bloated for my taste)
|
||||
|
||||
volumes = [
|
||||
"/etc/localtime:/etc/localtime:ro"
|
||||
"/etc/timezone:/etc/timezone:ro"
|
||||
];
|
||||
|
||||
user = "${builtins.toString UID}";
|
||||
|
||||
extraOptions = [
|
||||
"--group-add=${builtins.toString config.users.groups.geesefs.gid}"
|
||||
"--mount=type=bind,source=/srv/forgejo/data,target=/var/lib/gitea"
|
||||
];
|
||||
|
||||
ports = [
|
||||
"2222:2222"
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services.docker-forgejo.after = [ "postgresql.service" "gocryptfs.service" ];
|
||||
|
||||
systemd.services.forgejo-clear-actions-logs = {
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "forgejo";
|
||||
ExecStart = "${pkgs.nodejs_22}/bin/nodejs ${./clear-actions-logs.mjs}";
|
||||
};
|
||||
startAt = "03:00";
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /srv/forgejo/repos 0700 ${builtins.toString UID} ${builtins.toString UID} -"
|
||||
];
|
||||
|
||||
services.nginx.virtualHosts."git.stupid.fish" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "stupid.fish";
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://forgejo.docker:3000$request_uri";
|
||||
proxyWebsockets = true;
|
||||
|
||||
extraConfig = ''
|
||||
client_max_body_size 1g;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_send_timeout 120s;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 2222 ];
|
||||
}
|
8
hosts/koi/containers/forgejo/image/Dockerfile
Normal file
8
hosts/koi/containers/forgejo/image/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
|||
FROM codeberg.org/forgejo/forgejo:9.0.3-rootless
|
||||
|
||||
USER root
|
||||
|
||||
RUN apk add --no-cache shadow openssh && \
|
||||
usermod -u 1125 git
|
||||
|
||||
USER git
|
|
@ -1,4 +1,4 @@
|
|||
{ pkgs, ... }:
|
||||
{ pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
@ -11,15 +11,13 @@
|
|||
pkcs11.enable = true;
|
||||
};
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.loader.secureboot = {
|
||||
enable = true;
|
||||
# generated with sbctl
|
||||
signingKeyPath = "/etc/secureboot/keys/db/db.key";
|
||||
signingCertPath = "/etc/secureboot/keys/db/db.pem";
|
||||
};
|
||||
boot.loader.systemd-boot.configurationLimit = 15;
|
||||
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||
|
||||
boot.initrd.systemd.enable = true;
|
||||
boot.initrd.luks.devices.root.crypttabExtraOpts = [ "tpm2-device=auto" ];
|
||||
|
||||
boot.lanzaboote = {
|
||||
enable = true;
|
||||
pkiBundle = "/var/lib/sbctl";
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
let
|
||||
UID = 1126;
|
||||
in {
|
||||
desu.secrets.forgejo-runners-token = {};
|
||||
desu.secrets.forgejo-runners-token-sf = {};
|
||||
|
||||
users.users.actions-runner = {
|
||||
isNormalUser = true;
|
||||
uid = 1126;
|
||||
};
|
||||
|
||||
systemd.services.actions-runner-build-dind = {
|
||||
description = "dind image builder for actions runner";
|
||||
|
@ -9,28 +17,44 @@
|
|||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.docker}/bin/docker build -t local/actions-runner-dind -f ${./Dockerfile.dind} .";
|
||||
ExecStart = "${pkgs.docker}/bin/docker build -t local/actions-runner-dind ${pkgs.copyPathToStore ./image-dind}";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.gitea-runner-koi.requires = [ "actions-runner-build-dind.service" ];
|
||||
systemd.services.gitea-runner-koi-stupid-fish.requires = [ "actions-runner-build-dind.service" ];
|
||||
|
||||
services.gitea-actions-runner = {
|
||||
package = pkgs.forgejo-runner;
|
||||
instances.koi = {
|
||||
name = "koi";
|
||||
enable = true;
|
||||
url = "https://codeberg.org";
|
||||
tokenFile = config.desu.secrets.forgejo-runners-token.path;
|
||||
url = "https://git.stupid.fish";
|
||||
tokenFile = config.desu.secrets.forgejo-runners-token-sf.path;
|
||||
labels = [
|
||||
"node18:docker://node:18-bullseye"
|
||||
"node20:docker://node:20-bullseye"
|
||||
"node22:docker://node:22-bullseye"
|
||||
"docker:docker://local/actions-runner-dind"
|
||||
# fun fact: the actual image doesnt matter! it's only used to determine the runner
|
||||
"docker:docker://node:22-bullseye"
|
||||
];
|
||||
settings = {
|
||||
runner.capacity = 8;
|
||||
};
|
||||
};
|
||||
|
||||
# a separate runner for dind because it requires privileged mode and act-runner doesnt support setting --privileged for certain images
|
||||
instances.koi-dind = {
|
||||
name = "koi-dind";
|
||||
enable = true;
|
||||
url = "https://git.stupid.fish";
|
||||
tokenFile = config.desu.secrets.forgejo-runners-token-sf.path;
|
||||
labels = [
|
||||
"docker-dind:docker://local/actions-runner-dind"
|
||||
];
|
||||
settings = {
|
||||
container.privileged = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,12 +1,20 @@
|
|||
FROM node:23.4.0-alpine AS node
|
||||
|
||||
FROM docker:27-dind
|
||||
FROM docker:27-dind-rootless
|
||||
|
||||
USER root
|
||||
|
||||
COPY --from=node /usr/local/bin/node /usr/local/bin/node
|
||||
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
|
||||
COPY --from=node /usr/local/include/node /usr/local/include/node
|
||||
COPY ./start-dockerd.sh /opt/start-dockerd.sh
|
||||
|
||||
RUN apk add libstdc++ bash && \
|
||||
ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
|
||||
ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx && \
|
||||
ln -s /usr/local/lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack
|
||||
ln -s /usr/local/lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack && \
|
||||
ln -s /run/user/1000/docker.sock /var/run/docker.sock
|
||||
|
||||
ENV DOCKER_HOST=unix:///run/user/1000/docker.sock
|
||||
|
||||
USER rootless
|
21
hosts/koi/services/actions-runner/image-dind/start-dockerd.sh
Executable file
21
hosts/koi/services/actions-runner/image-dind/start-dockerd.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if docker info &> /dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
nohup /usr/local/bin/dockerd-entrypoint.sh > /home/rootless/dockerd.log 2>&1 &
|
||||
export DOCKER_HOST=unix:///run/user/1000/docker.sock
|
||||
|
||||
# wait for docker to start
|
||||
retry=0
|
||||
while ! docker info &> /dev/null; do
|
||||
sleep 1
|
||||
retry=$((retry + 1))
|
||||
if [ $retry -gt 15 ]; then
|
||||
echo "Failed to start dockerd after 15 seconds"
|
||||
exit 1
|
||||
fi
|
||||
done
|
|
@ -85,3 +85,7 @@ locations:
|
|||
from: /srv/vaultwarden/
|
||||
to: rclone
|
||||
cron: '0 6 * * *'
|
||||
forgejo:
|
||||
from: /srv/forgejo/
|
||||
to: rclone
|
||||
cron: '0 */6 * * *'
|
||||
|
|
|
@ -5,5 +5,12 @@
|
|||
forceSSL = true;
|
||||
useACMEHost = "stupid.fish";
|
||||
root = pkgs.copyPathToStore ./assets;
|
||||
|
||||
locations."/jetbra/" = {
|
||||
extraConfig = ''
|
||||
alias /mnt/s3-desu-priv-encrypted/jetbra/;
|
||||
try_files $uri $uri/ /index.html;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -90,5 +90,6 @@
|
|||
extraDomainNames = [ "*.s3.stupid.fish" ];
|
||||
};
|
||||
};
|
||||
users.users.nginx.extraGroups = [ "geesefs" ];
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "homura";
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "madoka";
|
||||
}
|
26
hosts/madoka/common.nix
Normal file
26
hosts/madoka/common.nix
Normal file
|
@ -0,0 +1,26 @@
|
|||
{ abs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/minimal.nix")
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
boot.tmp.cleanOnBoot = true;
|
||||
zramSwap.enable = true;
|
||||
|
||||
age.identityPaths = [
|
||||
"/etc/ssh/agenix_key"
|
||||
];
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keyFiles = [
|
||||
(abs "ssh/teidesu.pub")
|
||||
];
|
||||
|
||||
virtualisation.docker.enable = true;
|
||||
virtualisation.oci-containers.backend = "docker";
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
}
|
35
hosts/madoka/configuration.nix
Normal file
35
hosts/madoka/configuration.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
{ modulesPath, abs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/minimal.nix")
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
(abs "lib/desu")
|
||||
./hardware-configuration.nix
|
||||
./services/license-servers.nix
|
||||
];
|
||||
|
||||
boot.tmp.cleanOnBoot = true;
|
||||
zramSwap.enable = true;
|
||||
|
||||
age.identityPaths = [
|
||||
"/etc/ssh/agenix_key"
|
||||
];
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keyFiles = [
|
||||
(abs "ssh/teidesu.pub")
|
||||
];
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
|
||||
virtualisation.docker.enable = true;
|
||||
virtualisation.oci-containers.backend = "docker";
|
||||
|
||||
services.desu-deploy = {
|
||||
enable = true;
|
||||
key = builtins.readFile (abs "ssh/desu-deploy.pub");
|
||||
};
|
||||
|
||||
networking.hostName = "madoka";
|
||||
}
|
8
hosts/madoka/deploy.sh
Executable file
8
hosts/madoka/deploy.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -eau
|
||||
|
||||
SCRIPT=$(realpath "$0")
|
||||
SCRIPTPATH=$(dirname "$SCRIPT")
|
||||
|
||||
$SCRIPTPATH/../../switch --remote root@madoka .#madoka
|
14
hosts/madoka/hardware-configuration.nix
Normal file
14
hosts/madoka/hardware-configuration.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
boot.loader.grub = {
|
||||
efiSupport = true;
|
||||
efiInstallAsRemovable = true;
|
||||
device = "nodev";
|
||||
};
|
||||
|
||||
fileSystems."/boot" = { device = "/dev/disk/by-uuid/6514-E9BA"; fsType = "vfat"; };
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi" ];
|
||||
boot.initrd.kernelModules = [ "nvme" ];
|
||||
fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; };
|
||||
}
|
66
hosts/madoka/services/license-servers.nix
Normal file
66
hosts/madoka/services/license-servers.nix
Normal file
|
@ -0,0 +1,66 @@
|
|||
{ config, ... }:
|
||||
|
||||
let
|
||||
UID = 1100;
|
||||
in {
|
||||
desu.secrets.license-servers-env.owner = "license-servers";
|
||||
desu.secrets.forgejo-packages-token = {};
|
||||
desu.secrets.cloudflare-email.owner = "acme";
|
||||
desu.secrets.cloudflare-token.owner = "acme";
|
||||
|
||||
users.groups.acme.gid = 993;
|
||||
users.users.license-servers = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "acme" ];
|
||||
uid = UID;
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers.license-servers = {
|
||||
image = "git.stupid.fish/zachem/license-servers:latest";
|
||||
login = {
|
||||
registry = "https://git.stupid.fish";
|
||||
username = "teidesu";
|
||||
passwordFile = config.desu.secrets.forgejo-packages-token.path;
|
||||
};
|
||||
environment = {
|
||||
PUBLIC_HOSTNAME = "license.stupid.fish";
|
||||
|
||||
TLS_KEY_FILE = "/mnt/acme/key.pem";
|
||||
TLS_CERT_FILE = "/mnt/acme/cert.pem";
|
||||
};
|
||||
environmentFiles = [
|
||||
config.desu.secrets.license-servers-env.path
|
||||
];
|
||||
user = builtins.toString UID;
|
||||
extraOptions = [
|
||||
"--group-add=${builtins.toString config.users.groups.acme.gid}"
|
||||
"--mount=type=bind,source=/srv/license-servers/certs,target=/app/certs"
|
||||
"--mount=type=bind,source=/var/lib/acme/license.stupid.fish,target=/mnt/acme"
|
||||
];
|
||||
ports = [
|
||||
"80:80"
|
||||
"443:443"
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services.docker-license-servers.requires = [ "acme-finished-license.stupid.fish.target" ];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /srv/license-servers/certs 0700 ${builtins.toString UID} ${builtins.toString UID} -"
|
||||
];
|
||||
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.defaults = {
|
||||
email = "alina@tei.su";
|
||||
dnsProvider = "cloudflare";
|
||||
credentialFiles = {
|
||||
"CLOUDFLARE_EMAIL_FILE" = config.desu.secrets.cloudflare-email.path;
|
||||
"CLOUDFLARE_API_KEY_FILE" = config.desu.secrets.cloudflare-token.path;
|
||||
};
|
||||
};
|
||||
security.acme.certs = {
|
||||
"license.stupid.fish" = {};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
}
|
Binary file not shown.
6
secrets/forgejo-runners-token-sf.age
Normal file
6
secrets/forgejo-runners-token-sf.age
Normal file
|
@ -0,0 +1,6 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 sj88Xw GgKRg7idO0vDye/NcBuaMhcg1hd9xyCg6akWbg9mbm8
|
||||
ygNUeOABd0xR9J2QvAOTIATzh2uRHJUrZgwHOxvABQs
|
||||
--- uNOL20nKtDdHPt7C50jH7qB7FZZAP2SSw8kSQzRBCcI
|
||||
/%åÂÁç·D›f×}Ì/‘´F*0<>iÖn2Bë¥F
|
||||
x§›*îgÓÅ®ê–N±Hfùš[µ•®YÀÅrzQö`ü³ÐUsØ%¤¿
|
Loading…
Reference in a new issue