Initial clean commit

This commit is contained in:
randogoth 2026-02-05 17:57:02 +02:00
commit 1862821f8f
15 changed files with 1240 additions and 0 deletions

10
.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
/.envrc
/.gitconfig-nix
/.ssh-nix-config
/.direnv/
/secrets/age/keys.txt
/secrets/ssh/codeberg_id_ed25519
/result
/result/
/*.qcow2
/server.md

3
.sops.yaml Normal file
View file

@ -0,0 +1,3 @@
creation_rules:
- path_regex: secrets/.*\.ya?ml
age: age1647c5f46njylggj33h26t6twhq57n5qeaza04l845uy0fksv0ucsq82c3d

151
agents.md Normal file
View file

@ -0,0 +1,151 @@
# NixOS Migration and Configuration Agent
## Directive
Investigate server tobias@bucur for full reproducibility with Nix.
- Enumerate all publicly exposed services (native or containerized)
- Identify their repositories/images and configurations
- Record findings as a `[ ]` checklist in `server.md`
Do not implement flake modules until each checklist item is explicitly approved.
When implementing, produce or modify **Nix code only**.
No explanations unless explicitly requested.
If information is missing or unclear, stop and ask. Do not infer.
---
## Role
Expert NixOS agent focused on:
- Flake-first NixOS
- Modular NixOS systems
- Flake-contained host modules (“configuration.nix-style”)
- Deterministic, reproducible configurations
---
## Authority
- `flake.nix` is the sole entry point
- All evaluation via `outputs`
- No channels, no `NIX_PATH`, no `/etc/nixos`
- All systems are flakes
Legacy `configuration.nix` **must not** be an entry point.
Files resembling it are allowed **only** as flake-contained host modules.
---
## Workflow (Strict)
### Before any changes
- Present a plan
- Bullet points only
- Exact file paths
- Intent per file
- No code, no prose
Only approved files may be modified.
### Permission Gates
Explicit approval required **each time** before:
- Builds, tests, or evaluations
- Commits
- Pushing to remotes
---
## Modules
### Host Modules
- Path: `hosts/*.nix`
- Composition only
- Small, declarative
- No reusable logic
Allowed:
- `imports`
- Host-specific values (hostname, locale, timezone, `system.stateVersion`)
- Small, truly host-unique overrides
Forbidden:
- Reusable features
- Large logic blocks
- Inline user definitions
- Services usable by multiple hosts
- Monolithic system configs
**Rule:**
> Host modules compose. Feature modules implement.
### Feature Modules
- Path: `modules/**`
- Implementation only
- Reusable
- Upstream NixOS options only
- No custom option namespaces
---
## Home Manager
- No home-manager
- No `home-manager.users.*`
- `modules/users/*` manages accounts and user settings
---
## Hardware
- Hardware modules allowed
- All hardware changes must be listed in the plan
- No unapproved disk, boot, or kernel changes
---
## Overlays
- Allowed but discouraged
- Never introduce unless explicitly requested
- Prefer:
- flake inputs
- `callPackage`
- direct package references
---
## Code Style
### Nix
- Pure Nix
- Explicit attribute paths
- Prefer `lib.mkIf`, `lib.mkMerge`, `lib.optionals`
- Avoid `with pkgs;`, implicit imports, inline shell hacks
### Formatting
- `nixfmt-rfc-style`
- Do not reformat unrelated files
---
## Scripting
- Scripts live in `./scripts/`
- Deterministic, non-interactive
- POSIX only
- Minimal
- Never inline scripts in Nix
---
## Layout
```text
flake.nix # authority
hosts/ # composition
modules/ # behavior
scripts/

167
flake.lock generated Normal file
View file

@ -0,0 +1,167 @@
{
"nodes": {
"flux_vision": {
"flake": false,
"locked": {
"lastModified": 1766774843,
"narHash": "sha256-/bikoewxigIU4SJUhq3CwPA0fqPAhi53lXdH8QcfN98=",
"ref": "refs/heads/main",
"rev": "ff83815c4a781ff84de4c29ee656e078ca879fef",
"revCount": 17,
"type": "git",
"url": "https://codeberg.org/randogoth/flux.vision.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/randogoth/flux.vision.git"
}
},
"geoblog_plugin": {
"flake": false,
"locked": {
"lastModified": 1683036417,
"narHash": "sha256-0kGJfd72WLlAZ3X2tQ7Vwodsu/qKAW0cOcSpeRdPCnM=",
"ref": "refs/heads/main",
"rev": "840d907235d1a81b8ebfa0345f5e848452d69d60",
"revCount": 2,
"type": "git",
"url": "https://codeberg.org/randogoth/geoblog-plugin.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/randogoth/geoblog-plugin.git"
}
},
"nfc_web": {
"flake": false,
"locked": {
"lastModified": 1766145802,
"narHash": "sha256-Ptq4ySrE0muiAlhkt6QT2x+u0Ux1wLJQ9Rqlq2YUmHw=",
"ref": "refs/heads/main",
"rev": "6bd590bcd113b6159edcdf8beaf66629ea7aa8dc",
"revCount": 71,
"type": "git",
"url": "https://codeberg.org/randogoth/nfc-web.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/randogoth/nfc-web.git"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1770136044,
"narHash": "sha256-tlFqNG/uzz2++aAmn4v8J0vAkV3z7XngeIIB3rM3650=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e576e3c9cf9bad747afcddd9e34f51d18c855b4e",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"praxis": {
"flake": false,
"locked": {
"lastModified": 1766389293,
"narHash": "sha256-noQDF8WKsGDR1lght9xaWXg0O8W8wPAhSoX2jwGIbRg=",
"ref": "refs/heads/master",
"rev": "dda2c101079b7d7e6563aa40edc1057ada710a9f",
"revCount": 1,
"type": "git",
"url": "https://codeberg.org/randogoth/praxis.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/randogoth/praxis.git"
}
},
"root": {
"inputs": {
"flux_vision": "flux_vision",
"geoblog_plugin": "geoblog_plugin",
"nfc_web": "nfc_web",
"nixpkgs": "nixpkgs",
"praxis": "praxis",
"scopesessions": "scopesessions",
"sops-nix": "sops-nix",
"sublunar": "sublunar",
"sublunar_almanac": "sublunar_almanac"
}
},
"scopesessions": {
"flake": false,
"locked": {
"lastModified": 1766407123,
"narHash": "sha256-f1D1pEHGAhZ96Mt7R9vxWsi3dH+THeflSroRlUIgMxU=",
"ref": "refs/heads/main",
"rev": "36bfce14b41942eda24bd763b8f6613141a55a1f",
"revCount": 227,
"type": "git",
"url": "https://codeberg.org/randogoth/scopesessions.org.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/randogoth/scopesessions.org.git"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1770145881,
"narHash": "sha256-ktjWTq+D5MTXQcL9N6cDZXUf9kX8JBLLBLT0ZyOTSYY=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "17eea6f3816ba6568b8c81db8a4e6ca438b30b7c",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
}
},
"sublunar": {
"flake": false,
"locked": {
"lastModified": 1766145247,
"narHash": "sha256-XFAM+eD+GUDR3G+daOcPn2nLj5CZp+m/IwpSVmEYDrU=",
"ref": "refs/heads/main",
"rev": "4920396e8e9a5de9d93cb01f107823c9295f5bc2",
"revCount": 435,
"type": "git",
"url": "https://codeberg.org/randogoth/sublunar.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/randogoth/sublunar.git"
}
},
"sublunar_almanac": {
"flake": false,
"locked": {
"lastModified": 1766409110,
"narHash": "sha256-+xlqzuTsV5fUqmDWlPFrEcmThUCq9Yxh6j65DQtINkM=",
"ref": "refs/heads/main",
"rev": "c10e0a0bf27a685b8c00c6ed986f0616b7b7ba3d",
"revCount": 84,
"type": "git",
"url": "https://codeberg.org/randogoth/sublunar.almanac.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/randogoth/sublunar.almanac.git"
}
}
},
"root": "root",
"version": 7
}

52
flake.nix Normal file
View file

@ -0,0 +1,52 @@
{
description = "Bucur NixOS configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
sublunar.url = "git+https://codeberg.org/randogoth/sublunar.git";
sublunar.flake = false;
flux_vision.url = "git+https://codeberg.org/randogoth/flux.vision.git";
flux_vision.flake = false;
nfc_web.url = "git+https://codeberg.org/randogoth/nfc-web.git";
nfc_web.flake = false;
scopesessions.url = "git+https://codeberg.org/randogoth/scopesessions.org.git";
scopesessions.flake = false;
sublunar_almanac.url = "git+https://codeberg.org/randogoth/sublunar.almanac.git";
sublunar_almanac.flake = false;
praxis.url = "git+https://codeberg.org/randogoth/praxis.git";
praxis.flake = false;
geoblog_plugin.url = "git+https://codeberg.org/randogoth/geoblog-plugin.git";
geoblog_plugin.flake = false;
};
outputs = { self, nixpkgs, sops-nix, ... }@inputs:
let
system = "x86_64-linux";
in
{
nixosConfigurations.bucur = nixpkgs.lib.nixosSystem {
inherit system;
specialArgs = { inherit inputs; };
modules = [
sops-nix.nixosModules.sops
./hosts/bucur.nix
./modules/services/caddy.nix
./modules/services/openssh.nix
./modules/services/firewall.nix
./modules/services/tailscale.nix
./modules/services/podman.nix
./modules/services/static-sites
./modules/users/tobias.nix
];
};
};
}

16
hosts/bucur.nix Normal file
View file

@ -0,0 +1,16 @@
{ lib, ... }:
{
networking.hostName = "bucur";
time.timeZone = "UTC";
i18n.defaultLocale = "en_US.UTF-8";
system.stateVersion = "25.11";
virtualisation.vmVariant = {
users.mutableUsers = false;
users.users.tobias.password = "admin";
users.users.tobias.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILXTPk7gb4VDb+jORGw2sKp2SRTzoibXew6DqJJ0A3Zs randogoth@mrht"
];
services.firewalld.enable = lib.mkForce false;
};
}

View file

@ -0,0 +1,64 @@
{ pkgs, ... }:
{
services.caddy.enable = true;
services.caddy.configFile = pkgs.writeText "Caddyfile" ''
http:// {
root * /usr/share/caddy
file_server
}
privatpraxis-last-heidelberg.de, www.privatpraxis-last-heidelberg.de {
root * /var/www/privatpraxis-last-heidelberg.de/public
encode zstd gzip
file_server
}
raayoni-last.com, www.raayoni-last.com, flux.vision, www.flux.vision {
redir https://tobias.raayoni-last.com
}
tobias.raayoni-last.com {
root * /var/www/raayoni-last.com/tobias/public
encode zstd gzip
file_server
}
randogoth.com, www.randogoth.com {
root * /var/www/raayoni-last.com/tobias/public
encode zstd gzip
file_server
}
sublunar.space, www.sublunar.space {
root * /var/www/sublunar.space/public
encode zstd gzip
file_server
}
almanac.sublunar.space {
root * /var/www/sublunar.space/almanac/public
encode zstd gzip
@wasm {
path /js/*.wasm
}
header @wasm Content-Type application/wasm
file_server
}
scopesessions.org, www.scopesessions.org {
root * /var/www/scopesessions.org/public
encode zstd gzip
file_server
}
nmns.place, www.nmns.place {
root * /var/www/nmns.place/public
encode zstd gzip
file_server
}
import Caddyfile.d/*.caddyfile
'';
}

View file

@ -0,0 +1,104 @@
{ ... }:
{
networking.firewall.enable = true;
networking.firewall.backend = "firewalld";
networking.nftables.enable = true;
services.firewalld.enable = true;
services.firewalld.settings.DefaultZone = "FedoraServer";
services.firewalld.zones.FedoraServer = {
target = "%%REJECT%%";
interfaces = [ "ens3" ];
forward = true;
services = [ "http" "https" "ssh" ];
ports = [
{
port = 8443;
protocol = "tcp";
}
];
rules = [
{
rule = {
"@family" = "ipv4";
source = { "@address" = "80.94.92.177"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "45.148.10.240"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "193.242.125.233"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "45.78.198.204"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "176.120.22.47"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "91.202.233.33"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "188.166.24.102"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "128.1.47.28"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "188.166.11.218"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
{
rule = {
"@family" = "ipv4";
source = { "@address" = "104.248.91.222"; };
port = { "@port" = "ssh"; "@protocol" = "tcp"; };
reject = { "@type" = "icmp-port-unreachable"; };
};
}
];
};
}

View file

@ -0,0 +1,13 @@
{ ... }:
{
services.openssh.enable = true;
services.openssh.settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
AllowTcpForwarding = "no";
X11Forwarding = false;
UseDns = false;
MaxAuthTries = 3;
};
}

View file

@ -0,0 +1,39 @@
{ config, ... }:
{
environment.etc."sops/age/keys.txt".source = ../../secrets/age/keys.txt;
sops.defaultSopsFile = ../../secrets/bucur.yaml;
sops.age.keyFile = "/etc/sops/age/keys.txt";
sops.secrets.mtproto_secret = {};
sops.templates."mtproto-proxy.env".content = ''
SECRET=${config.sops.placeholder."mtproto_secret"}
'';
virtualisation.podman.enable = true;
virtualisation.oci-containers.backend = "podman";
virtualisation.oci-containers.containers = {
portainer = {
image = "docker.io/portainer/portainer-ce:lts";
autoStart = true;
ports = [
"100.124.109.92:8000:8000"
"100.124.109.92:9443:9443"
];
volumes = [
"portainer_data:/data"
"/run/podman/podman.sock:/var/run/docker.sock"
];
extraOptions = [ "--privileged" ];
};
mtproto-proxy = {
image = "docker.io/telegrammessenger/proxy:latest";
autoStart = true;
ports = [ "0.0.0.0:8443:443" ];
volumes = [ "mtproxy-data:/data" ];
environmentFiles = [ config.sops.templates."mtproto-proxy.env".path ];
};
};
}

View file

@ -0,0 +1,160 @@
{ inputs, pkgs, ... }:
let
buildPelicanSite = { name, src, subdir ? "", pluginSources ? [ ] }:
let
workdir = if subdir == "" then "." else subdir;
pythonEnv = pkgs.python3.withPackages (ps: [
ps.pelican
ps.markdown
ps.pygments
]);
copyPlugins = pkgs.lib.concatStringsSep "\n" (map (plugin: ''
mkdir -p "${workdir}/${plugin.dest}"
cp -a "${plugin.src}${if plugin ? subdir then "/${plugin.subdir}" else ""}/." "${workdir}/${plugin.dest}/"
'') pluginSources);
in
pkgs.stdenvNoCC.mkDerivation {
pname = name;
version = "git";
src = src;
nativeBuildInputs = [ pythonEnv ];
buildPhase = ''
runHook preBuild
cd ${workdir}
${copyPlugins}
${pythonEnv}/bin/pelican content -o "$out"
runHook postBuild
'';
installPhase = "true";
};
buildJekyllSite = { name, src, gemset }:
let
bundlerEnv = pkgs.bundlerEnv {
name = "${name}-bundler-env";
gemdir = src;
gemset = gemset;
};
in
pkgs.stdenvNoCC.mkDerivation {
pname = name;
version = "git";
src = src;
nativeBuildInputs = [ bundlerEnv ];
buildPhase = ''
runHook preBuild
JEKYLL_ENV=production bundle exec jekyll build -s . -d "$out"
runHook postBuild
'';
installPhase = "true";
};
buildStaticSite = { name, src, subdir ? "" }:
let
srcPath = if subdir == "" then src else "${src}/${subdir}";
in
pkgs.stdenvNoCC.mkDerivation {
pname = name;
version = "git";
src = src;
dontUnpack = true;
installPhase = ''
runHook preInstall
mkdir -p "$out"
cp -a ${srcPath}/. "$out/"
runHook postInstall
'';
};
mkDeployService = { name, src, dest }:
{
description = "Deploy ${name} site";
path = [ pkgs.coreutils pkgs.rsync ];
serviceConfig = {
Type = "oneshot";
};
script = ''
install -d -m 755 ${dest}
rsync -a --delete ${src}/ ${dest}/
'';
};
sublunarSite = buildPelicanSite {
name = "sublunar";
src = inputs.sublunar;
};
tobiasRaayoniLastSite = buildPelicanSite {
name = "tobias-raayoni-last";
src = inputs.flux_vision;
subdir = "web";
};
nmnsSite = buildPelicanSite {
name = "nmns";
src = inputs.nfc_web;
subdir = "web";
};
scopesessionsSite = buildJekyllSite {
name = "scopesessions";
src = inputs.scopesessions;
gemset = ./scopesessions-gemset.nix;
};
almanacSite = buildStaticSite {
name = "sublunar-almanac";
src = inputs.sublunar_almanac;
};
praxisSite = buildStaticSite {
name = "praxis";
src = inputs.praxis;
};
isNixBuild = builtins.getEnv "IN_NIX_BUILD" == "1";
in
{
sops.secrets.codeberg_id_ed25519 = {
owner = "root";
group = "root";
mode = "0400";
path = "/etc/ssh/codeberg_id_ed25519";
};
systemd.services."deploy-sublunar" = mkDeployService {
name = "sublunar";
src = sublunarSite;
dest = "/var/www/sublunar.space/public";
};
systemd.services."deploy-tobias-raayoni-last" = mkDeployService {
name = "tobias-raayoni-last";
src = tobiasRaayoniLastSite;
dest = "/var/www/raayoni-last.com/tobias/public";
};
systemd.services."deploy-nmns" = mkDeployService {
name = "nmns";
src = nmnsSite;
dest = "/var/www/nmns.place/public";
};
systemd.services."deploy-scopesessions" = mkDeployService {
name = "scopesessions";
src = scopesessionsSite;
dest = "/var/www/scopesessions.org/public";
};
systemd.services."deploy-almanac" = mkDeployService {
name = "almanac";
src = almanacSite;
dest = "/var/www/sublunar.space/almanac/public";
};
systemd.services."deploy-privatpraxis" = mkDeployService {
name = "privatpraxis";
src = praxisSite;
dest = "/var/www/privatpraxis-last-heidelberg.de/public";
};
}

View file

@ -0,0 +1,419 @@
{
addressable = {
dependencies = ["public_suffix"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0mxhjgihzsx45l9wh2n0ywl9w0c6k70igm5r0d63dxkcagwvh4vw";
type = "gem";
};
version = "2.8.8";
};
base64 = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0yx9yn47a8lkfcjmigk79fykxvr80r4m1i35q82sxzynpbm7lcr7";
type = "gem";
};
version = "0.3.0";
};
bigdecimal = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "19y406nx17arzsbc515mjmr6k5p59afprspa1k423yd9cp8d61wb";
type = "gem";
};
version = "4.0.1";
};
colorator = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0f7wvpam948cglrciyqd798gdc6z3cfijciavd0dfixgaypmvy72";
type = "gem";
};
version = "1.1.0";
};
concurrent-ruby = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1aymcakhzl83k77g2f2krz07bg1cbafbcd2ghvwr4lky3rz86mkb";
type = "gem";
};
version = "1.3.6";
};
csv = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0gz7r2kazwwwyrwi95hbnhy54kwkfac5swh2gy5p5vw36fn38lbf";
type = "gem";
};
version = "3.3.5";
};
em-websocket = {
dependencies = ["eventmachine" "http_parser.rb"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1a66b0kjk6jx7pai9gc7i27zd0a128gy73nmas98gjz6wjyr4spm";
type = "gem";
};
version = "0.5.3";
};
eventmachine = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0wh9aqb0skz80fhfn66lbpr4f86ya2z5rx6gm5xlfhd05bj1ch4r";
type = "gem";
};
version = "1.2.7";
};
faraday = {
dependencies = ["faraday-net_http" "json" "logger"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1ka175ci0q9ylpcy651pjj580diplkaskycn4n7jcmbyv7jwz6c6";
type = "gem";
};
version = "2.14.0";
};
faraday-net_http = {
dependencies = ["net-http"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0v4hfmc7d4lrqqj2wl366rm9551gd08zkv2ppwwnjlnkc217aizi";
type = "gem";
};
version = "3.4.2";
};
ffi = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "19kdyjg3kv7x0ad4xsd4swy5izsbb1vl1rpb6qqcqisr5s23awi9";
type = "gem";
};
version = "1.17.2";
};
forwardable-extended = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "15zcqfxfvsnprwm8agia85x64vjzr2w0xn9vxfnxzgcv8s699v0v";
type = "gem";
};
version = "2.6.0";
};
google-protobuf = {
dependencies = ["bigdecimal" "rake"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0583agdf2jvnq78scf8008bddrmbybn27ylyydg6bza2qvb510bl";
type = "gem";
};
version = "4.33.2";
};
"http_parser.rb" = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1gj4fmls0mf52dlr928gaq0c0cb0m3aqa9kaa6l0ikl2zbqk42as";
type = "gem";
};
version = "0.8.0";
};
i18n = {
dependencies = ["concurrent-ruby"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1994i044vdmzzkyr76g8rpl1fq1532wf0sb21xg5r1ilj5iphmr8";
type = "gem";
};
version = "1.14.8";
};
jekyll = {
dependencies = ["addressable" "base64" "colorator" "csv" "em-websocket" "i18n" "jekyll-sass-converter" "jekyll-watch" "json" "kramdown" "kramdown-parser-gfm" "liquid" "mercenary" "pathutil" "rouge" "safe_yaml" "terminal-table" "webrick"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1h8qpki1zcw4srnzmbba2gwajycm50w53kxq8l6vicm5azc484ac";
type = "gem";
};
version = "4.4.1";
};
jekyll-sass-converter = {
dependencies = ["sass-embedded"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0hr4hsir8lm8aw3yj9zi7hx2xs4k00xn9inh24642d6iy625v4l3";
type = "gem";
};
version = "3.1.0";
};
jekyll-watch = {
dependencies = ["listen"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1qd7hy1kl87fl7l0frw5qbn22x7ayfzlv9a5ca1m59g0ym1ysi5w";
type = "gem";
};
version = "2.2.1";
};
json = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "01fmiz052cvnxgdnhb3qwcy88xbv7l3liz0fkvs5qgqqwjp0c1di";
type = "gem";
};
version = "2.18.0";
};
kramdown = {
dependencies = ["rexml"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "131nwypz8b4pq1hxs6gsz3k00i9b75y3cgpkq57vxknkv6mvdfw7";
type = "gem";
};
version = "2.5.1";
};
kramdown-parser-gfm = {
dependencies = ["kramdown"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0a8pb3v951f4x7h968rqfsa19c8arz21zw1vaj42jza22rap8fgv";
type = "gem";
};
version = "1.1.0";
};
liquid = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1czxv2i1gv3k7hxnrgfjb0z8khz74l4pmfwd70c7kr25l2qypksg";
type = "gem";
};
version = "4.0.4";
};
listen = {
dependencies = ["rb-fsevent" "rb-inotify"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0rwwsmvq79qwzl6324yc53py02kbrcww35si720490z5w0j497nv";
type = "gem";
};
version = "3.9.0";
};
logger = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "00q2zznygpbls8asz5knjvvj2brr3ghmqxgr83xnrdj4rk3xwvhr";
type = "gem";
};
version = "1.7.0";
};
mercenary = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0f2i827w4lmsizrxixsrv2ssa3gk1b7lmqh8brk8ijmdb551wnmj";
type = "gem";
};
version = "0.4.0";
};
mini_magick = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1nfxjpmka12ihbwd87d5k2hh7d2pv3aq95x0l2lh8gca1s72bmki";
type = "gem";
};
version = "4.13.2";
};
net-http = {
dependencies = ["uri"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "15k96fj6qwbaiv6g52l538ass95ds1qwgynqdridz29yqrkhpfi5";
type = "gem";
};
version = "0.9.1";
};
pathutil = {
dependencies = ["forwardable-extended"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "12fm93ljw9fbxmv2krki5k5wkvr7560qy8p4spvb9jiiaqv78fz4";
type = "gem";
};
version = "0.16.2";
};
public_suffix = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "15dhl6k4gbax0xz8frfs4nsb6lg5zgax9vkr1pqzjmhfxddhn2gp";
type = "gem";
};
version = "7.0.0";
};
rake = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "175iisqb211n0qbfyqd8jz2g01q6xj038zjf4q0nm8k6kz88k7lc";
type = "gem";
};
version = "13.3.1";
};
rb-fsevent = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1zmf31rnpm8553lqwibvv3kkx0v7majm1f341xbxc0bk5sbhp423";
type = "gem";
};
version = "0.11.2";
};
rb-inotify = {
dependencies = ["ffi"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0vmy8xgahixcz6hzwy4zdcyn2y6d6ri8dqv5xccgzc1r292019x0";
type = "gem";
};
version = "0.11.1";
};
rexml = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0hninnbvqd2pn40h863lbrn9p11gvdxp928izkag5ysx8b1s5q0r";
type = "gem";
};
version = "3.4.4";
};
rouge = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1pkp5icgm7s10b2n6b2pzbdsfiv0l5sxqyizx55qdmlpaxnk8xah";
type = "gem";
};
version = "4.6.1";
};
safe_yaml = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0j7qv63p0vqcd838i2iy2f76c3dgwzkiz1d1xkg7n0pbnxj2vb56";
type = "gem";
};
version = "1.0.5";
};
sass-embedded = {
dependencies = ["google-protobuf" "rake"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1nb8wy2v397qi7hn3vamya6yv7v4ix2zfdsrk3mairslb24yhbhi";
type = "gem";
};
version = "1.97.1";
};
terminal-table = {
dependencies = ["unicode-display_width"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "14dfmfjppmng5hwj7c5ka6qdapawm3h6k9lhn8zj001ybypvclgr";
type = "gem";
};
version = "3.0.2";
};
unicode-display_width = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0nkz7fadlrdbkf37m0x7sw8bnz8r355q3vwcfb9f9md6pds9h9qj";
type = "gem";
};
version = "2.6.0";
};
uri = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1ijpbj7mdrq7rhpq2kb51yykhrs2s54wfs6sm9z3icgz4y6sb7rp";
type = "gem";
};
version = "1.1.1";
};
webrick = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0ca1hr2rxrfw7s613rp4r4bxb454i3ylzniv9b9gxpklqigs3d5y";
type = "gem";
};
version = "1.9.2";
};
}

View file

@ -0,0 +1,5 @@
{ ... }:
{
services.tailscale.enable = true;
services.tailscale.port = 41641;
}

20
modules/users/tobias.nix Normal file
View file

@ -0,0 +1,20 @@
{ pkgs, ... }:
{
users.users.tobias = {
isNormalUser = true;
uid = 1000;
group = "tobias";
extraGroups = [ "wheel" ];
home = "/home/tobias";
shell = pkgs.bashInteractive;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBgC4+zkTKNLPCt1vcTLyA+iwKGG8hrmcN2XKUExAR8W randogoth@mrht"
];
};
users.groups.tobias = {
gid = 1000;
};
security.sudo.wheelNeedsPassword = false;
}

17
secrets/bucur.yaml Normal file
View file

@ -0,0 +1,17 @@
mtproto_secret: ENC[AES256_GCM,data:MyzyUCH8cLOG+GMtmV03daJ9sqwOw/ozN2yi/14SMlY=,iv:LLf2LIvX+jNjRdMHclHpsmTZa7wmVM3gD6RbqeCGmik=,tag:i36lVESyKJafsn14kSzh3g==,type:str]
codeberg_id_ed25519: ENC[AES256_GCM,data:AZbFWfc80HVskenEVLYL9MOYrGhW7Cwzdqv8gS4+1JGfk+nC801SmMgElUdISo+3m/O54b8RbJtdVz2u99gL8WG6wgbK7xqf40q4HNvV5cFXp7L/ozUkT41uXjWsDIdnMwumOqL/vjXowmAay30kMOiD5M4DL0t6EmuOo1Rcdffe/HwCVd2Pz7ZpU+BSTQV/pDTK1X3taUCjCY3Ui0XrcSCY8G2tuX5pFQ6t+vLrdqy3UGhofYHQ+nZuoyEKQHCcvEhYvEgDPJtyy+gk96vZCDYyXb9am/5k0I+MoIsArpavp4P0r5dNDcTnuCHH+fVPTG4tOsG/Ztf1rFBCsqPiM0azNElI8FERSKLYipuDDD8GI46p43OalHw4pxmAHXNOs70PfIH25iFJ5AUb32v2A71LScJMNP/TFSSezuq6g5eTd/JrtpQnWwToH1eVrwcN/8YX3xflLZ2JO1q4fjCXrkYHyw004dV/HAq3u1XQDmfMviZiH80+hiVIgZLfMWv5IyzfuomqSnfOj6oJ6D+j,iv:37HiX60OnO/zZFs1v4VWQLxcaoC1byZ3N2ueYFh4BVQ=,tag:5+z2YlnA8+MEcQTTrYhPJA==,type:str]
sops:
age:
- recipient: age1647c5f46njylggj33h26t6twhq57n5qeaza04l845uy0fksv0ucsq82c3d
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpZWtwNDdiRlA0K25tbkZP
VDBrSVFCTlU4NlpqU2NHZnk1NEw4OEhXTTBJCktSU3pBcEZwN2NVNUl2ekNQY1Vp
YUdKbVE2ZzhUTmJwVDdRcVBpbXQ1b0EKLS0tIFZINGt1enNwUHlDdmZ4YTV6K09T
U0x1ZmtzLytSL1Y3cVo1ZVJ2Ymtob1EKTpgjSymQx14wLSuUhh5Txq++3DrLS4Bs
x8vVtQgcXZgv1q0OMGup6DT4bkY6UiNbn9bAt4rHCaRPeb15x4ZKNw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-05T14:18:42Z"
mac: ENC[AES256_GCM,data:sZTFVbWYhtYML6tZrivXYGm8ug+isUf7wi0VWwQ0Wx1Swany1RSkyQI7N0eFs58tVsY2KoizOShvLkC8UcpRvtog1M/OyZi0LypYkfMUD7Rth11AF2n3Tg4Q3VNH5DGcLWkzYleA4mj1mJnPyCQzKOykXSPocODAcKUyFYcP8uQ=,iv:ZxuNWYQesR6mtezi5yBRacPF4GC5NDsevaSlRJ+A6X4=,tag:htOCSco/V2/twoRRWeoBbA==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0