Compare commits

...

7 commits

20 changed files with 307 additions and 49 deletions

View file

@ -5,7 +5,8 @@
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
[
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ];
@ -14,19 +15,21 @@
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/439a1beb-1443-495b-9891-012605819803";
{
device = "/dev/disk/by-uuid/439a1beb-1443-495b-9891-012605819803";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/47A1-0296";
{
device = "/dev/disk/by-uuid/47A1-0296";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
fileSystems."/nas" = {
device = "/dev/disk/by-label/WD_RED_4T_1";
fsType = "ext4";
device = "/dev/disk/by-label/WD_RED_4T_1";
fsType = "ext4";
};
swapDevices = [ ];
@ -36,7 +39,24 @@
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp9s0.useDHCP = lib.mkDefault true;
networking.defaultGateway = "192.168.100.1";
networking.interfaces.enp9s0 = {
useDHCP = false;
ipv4.addresses = [
{
address = "192.168.100.3";
prefixLength = 24;
}
{
address = "192.168.100.4";
prefixLength = 24;
}
{
address = "192.168.100.5";
prefixLength = 24;
}
];
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;

View file

@ -1,32 +1,80 @@
{ config, pkgs, unstable, ... }:
{ config, pkgs, lib, unstable, ... }:
let
cfg = config.profile.neovim;
inherit (lib) mkIf;
repository = "git@github.com:tigorlazuardi/nvim.git";
nvimCloneDir = "${config.home.homeDirectory}/nvim";
in
{
home.file.".config/nvim" = {
source = ./.;
recursive = true;
config = mkIf cfg.enable {
systemd.user.services.clone-nvim = {
Unit = {
Description = "Clone neovim configuration if not exists";
Wants = [ "network-online.target" ];
After = [ "nss-lookup.target" ];
StartLimitIntervalSec = 300;
StartLimitBurst = 10;
};
Service =
let
git = "${pkgs.git}/bin/git";
bash = "${pkgs.bash}/bin/bash";
ping = "${pkgs.unixtools.ping}/bin/ping";
host = "github.com";
sleep = "${pkgs.coreutils}/bin/sleep";
script = pkgs.writeScriptBin "clone-nvim.sh" ''
#${bash}
if [ -d "${nvimCloneDir}" ]; then
exit 0;
fi
until ${ping} -c 1 ${host}; do
${sleep} 1;
done
${git} clone ${repository} ${nvimCloneDir}
'';
path = "${script}/bin/clone-nvim.sh";
in
{
Type = "simple";
ExecStart = path;
Restart = "on-failure";
RemainAfterExit = "yes";
};
Install = {
WantedBy = [ "default.target" ];
};
};
xdg.configFile.nvim = {
source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/nvim";
recursive = true;
};
sops.secrets."copilot" = {
path = "${config.home.homeDirectory}/.config/github-copilot/hosts.json";
};
home.packages = with pkgs; [
stylua
lua-language-server
docker-compose-language-service
emmet-ls
silicon # For code screenshots
###### Golang development tools ######
gomodifytags
gotests
iferr
curl
cargo
nixpkgs-fmt
nil
gcc
python3
];
};
sops.secrets."copilot" = {
path = "${config.home.homeDirectory}/.config/github-copilot/hosts.json";
};
home.packages = with pkgs; [
stylua
lua-language-server
docker-compose-language-service
emmet-ls
silicon # For code screenshots
###### Golang development tools ######
gomodifytags
gotests
iferr
curl
cargo
nixpkgs-fmt
nil
gcc
python3
];
}

View file

@ -29,4 +29,21 @@ in
};
services.mpris-proxy.enable = config.profile.mpris-proxy.enable;
sops.secrets =
let
sopsFile = ../secrets/ssh.yaml;
in
{
"ssh/id_ed25519/public" = {
inherit sopsFile;
path = "${config.home.homeDirectory}/.ssh/id_ed25519.pub";
mode = "0444";
};
"ssh/id_ed25519/private" = {
inherit sopsFile;
path = "${config.home.homeDirectory}/.ssh/id_ed25519";
mode = "0400";
};
};
}

View file

@ -19,6 +19,11 @@
default = "eth0";
};
neovim.enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
user = {
name = lib.mkOption {
type = lib.types.str;

View file

@ -1,11 +1,11 @@
{ lib, ... }:
let
inherit (lib) mkEnableOption;
in
{
options.profile.docker = {
enable = lib.mkEnableOption "docker";
caddy.enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
caddy.enable = mkEnableOption "caddy docker";
kavita.enable = lib.mkEnableOption "kavita docker";
};
}

View file

@ -4,5 +4,6 @@
enable = lib.mkEnableOption "podman";
caddy.enable = lib.mkEnableOption "caddy podman";
kavita.enable = lib.mkEnableOption "kavita podman";
pihole.enable = lib.mkEnableOption "pihole podman";
};
}

View file

@ -24,6 +24,11 @@
networking.firewall.allowedTCPPorts = [ 80 443 ];
podman = {
enable = true;
pihole.enable = true;
};
docker = {
enable = false;
};
services = {

View file

@ -1,4 +1,10 @@
runner_token: ENC[AES256_GCM,data:OA1qGIY46bNcjHDms3XZhpa40J9WRexNXsnK0Lm1WWIUbvKOCp6GG2v2599ysQ==,iv:ftNbVJYJR+2UozxMLcYZh5HH+O1KRMvUAKQc9/UAunI=,tag:F++kseVO3yD3jt6+vVTJ5Q==,type:str]
forgejo:
runners:
global: ENC[AES256_GCM,data:LuYqYDMgaq+L94JL5tGTlOhm7x98jpb7n6o5jYVKdN/9Z/5LA10lmwdDDsBYuA==,iv:UkLz8qW/C2M2XomRz+Oc+d4LIioxyh2pPgBaiY6x4N8=,tag:k0xRH8+gMoM4DbITXn1SfA==,type:str]
user_tokens:
tigor:
#ENC[AES256_GCM,data:5IEV/X4fpfydhdSw7LYOLMFZYqD/Kp96Zyp/YXnvFzVh8GluX4+9qGgsdWAsFgLlPXDRAi1ViA==,iv:v1OmczINHtT+AtdXMBjstmGejV62nhQ/T9aIoJG8DR8=,tag:b4Xg3ybhrxy70n/UB5D7nQ==,type:comment]
push_docker_image_token: ENC[AES256_GCM,data:jMTz+c3IEcpqRkYLZyrUWLWLIw0AOdDk7LsIDvjCW3rKxTiOOmb1wg==,iv:OjZArNhCCKZkngGjYbCQVYJkQww9K5b4ehUXxsdOqdU=,tag:EViefKbS+II+MXWqLE7rKw==,type:str]
sops:
kms: []
gcp_kms: []
@ -14,8 +20,8 @@ sops:
NGg4aFJsSHNPdTcwQ2ZMdmJscm5iNzgKRLrTAenr9q3r1dGPEyuxNhsQp8+20rCk
IKbsjenq/QTMQc+pMz/0oypVFUYNljmOfTWvvnjdJNsYHektNMkmNA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-06-13T12:44:00Z"
mac: ENC[AES256_GCM,data:x8MHb/bcXqQHOUfLIOjnk1ivCs+ubLKm6L0gzrI3ZbLaQRieKvY2THSDjmyF2OAe5x9stjCY5ZOb7t3Y7EXG5sgiwvSwqcZKUY3k4SEkJtO6MJmLE39UGphHPZXQD4Jez+PWfrbZXf4lk9hsnW20wHZgePq+w6mW003uN88ZPzw=,iv:gOZJIXcT2GGTcxonKPtjxZewjFDHU0FW0xT8Sfzz10o=,tag:keHB371hNXD90rqgZjfeaw==,type:str]
lastmodified: "2024-06-15T09:16:06Z"
mac: ENC[AES256_GCM,data:583xIAMkXyVNEkGeM2LM7CLRsypeeJ6Fpt3HxNw7jVmB3PFB/KKwcyhw4UDjNM2xsIjgGMjuAGc3SBI7zubfy9YotrP6m+NOw+8lC9JZbBQIaHIOPTgpeUJLHGveNe2SEBYfbhCjQid+EAWW92oRddZoGyrh2OWq33FgRvTM00A=,iv:/6mZEm2jyJ1cxOQ1mUoGHu6oZjWGknllKYF9/uV80Ao=,tag:oCYlwgXZuin7uBUeRjnOlw==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

22
secrets/pihole.yaml Normal file
View file

@ -0,0 +1,22 @@
pihole:
env: ENC[AES256_GCM,data:JLpWZwnefbu0mauukndehWjrsqjvnGdqKYev+UwqP3EoqG88o6c9,iv:u5iaBCjQdga/+O+/IN6dt86ElOO4sferh/BOnS/AXZw=,tag:4oRuUQJ8g11DkYGkRt6EPg==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1kruum2varzua7w5n6n52vhwyek2arc685rhcwt0u7k2jf5mecsjslkl9ll
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoWFhuaFp4Zm5idmFXUGRO
RG9YbzV3WUdJcHRFWlpISE5GNzVRZEpILzFvCjJUQlFqeWFsNU15Y1pINWgvc2wz
OU82L3ZPdW9GY1dyaXV4dndIUmNGRzQKLS0tIGpYMGZQeFJMMlhYUGR5c3lkbng2
VlpjTVo3NlIzR0QrVGZNdWdORjVMVmMKIrSq+w9oB3UdOxGNbwabXrpgPSfys+zo
M79xEqCUZ30jmfpPvL2VUiD25Bq/iWyj3x8d1xVGxQqUOg23AMb9mA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-06-16T17:29:06Z"
mac: ENC[AES256_GCM,data:e4VrmU1OtVuTxIz56NIumSoLTN2PDCYk5+f8UhPZyTF9rH/hz78LxhbPEPLy4TqQpxZZw/cH8wUUTNXUsYRdlbeL+IIbsEcwzjEBWZCSu38gMj/bNhBNwKU/oAWoKHdAQJYxYe3xnyji1xMLZofDVGQv2i46AI1TMXjFBU9Lz6Q=,iv:ILLCVVWxEKgVqCLHGuDmVINdgh0T3oYimdBIeWvQ7PE=,tag:7yvr0eEciG8yOVrHk1eGeg==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

24
secrets/ssh.yaml Normal file
View file

@ -0,0 +1,24 @@
ssh:
id_ed25519:
public: ENC[AES256_GCM,data:JmFWFRSIvgL4gzEwezyijkc11ll9GueYY2lxxmkPMqSz7zGnAcQ9+mQIU97MDyPp9eCQVPOIDDrWM8ct7+ji7Sxg25H80XlsvoKmawT8sPdzQ60DAumAdqNal3I=,iv:UivMLLFFCkIFcL8mCxIDPdDWlluxqhjpO7asnF8OUSg=,tag:zOeEALrhmHwSpmtiCX5mWg==,type:str]
private: ENC[AES256_GCM,data:kv5Qlt1yib7nhBj4z8CIuqNc7xmFCZgybZx41yMoeRGQimUy1Z++YaYRg5YKYmIIXSodsmFLrrR5zuIiysLn/5fI9eLsPYNiInerqTtE5SwHH6hwya/GX6gfh9bnakvWAd8J+jp2pgrCLDTT1V5TSL+t8APSs3pvMsmSfd+ojRrTFs7omY75gE91FAjlub/SmnDnlQHQMbBdfYhFY3zgiHzsSBD0SvHjiE3c6t3YsqS2CDxape78Z64+kJzTgL0dMiIAwzMZB3BH2ufnVMwi7FWYxA/dkqj2tFJLTwHaJQZgr/ou1oOng+MstLfpL/45toyDsjNzJe4dChDOdNzAmP8ZFdL2uXqSTy1biK03ifaGxDMaiDARFMUOEZNA1V3+RkariSfO129/0izAjtttlITughRMV3JRsvs81uIETVBp+S9kljsT1TIdlCNWspo8gvBI41DN4bnLFQCFip0HRGhC4F3oq49A/CV94An8IdwwwQwoxsaNeilJDwNnQDVdChhYoDa8ynvA00F+xJmh,iv:oKWlw2I9mXTdY2oq++rxA8IbOlfSHuB7QwilD1Q7Xas=,tag:zhhsiJ91XdBnR85MYG8+WQ==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1kruum2varzua7w5n6n52vhwyek2arc685rhcwt0u7k2jf5mecsjslkl9ll
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFeDU3eEwrNGljcmFueHFU
NEtrdVF5MU9ueTNDeTlCdmRPSFpnNFJDZTBzCnk4NU9ZcEc0YkhGcnNQVktNMDR2
a3dHTWV4RmNINlA1ZVhzSU9xNGtWVzQKLS0tIDF4dnRlQUo3OTJjNzFiYmlGVThE
M2pJUzhSUDFRWGtjdnNCZmlMT2puZlEKBxDLcxTU0E81lqqPQ75N5Et69Z1Dwac6
n3+oBzhhJoOhYagmp/Zm3FVh3kcHGoCe6pyDnrZSka/zO3kkZKigng==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-06-17T09:01:59Z"
mac: ENC[AES256_GCM,data:i2MCNIJ8LVspz878zTH7QrXOAA/8+G4xFhYGRoWmzCzRIHYAXsTDDU4ATgZM3rSqCWgvO/3ynKbGmiDN2z5tYreB8KDRk92WVuCqaJSfdnYulvgf1346+9NxbMbJnAi34evUcPj7QJTooRF0vGCIAk8zOCu75TIB8acVwFB+viY=,iv:9+rfk7QqLjNH0FZ617A2Y1vciwBBYlm54S2o1G93kb4=,tag:qz55kt+IFQDBt6vWK+v6Cw==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

View file

@ -1,9 +1,11 @@
{ config, lib, ... }:
let
cfg = config.profile.docker;
username = config.profile.user.name;
in
{
config = lib.mkIf cfg.enable {
users.users.${username}.extraGroups = [ "docker" ];
virtualisation.docker.enable = true;
virtualisation.docker.autoPrune.enable = true;
virtualisation.oci-containers.backend = "docker";

View file

@ -1,9 +1,11 @@
{ config, lib, pkgs, ... }:
let
cfg = config.profile.android;
username = config.profile.user.name;
in
{
config = lib.mkIf cfg.enable {
users.users.${username}.extraGroups = [ "adbusers" ];
programs.adb.enable = true;
environment.systemPackages = with pkgs; [
androidenv.androidPkgs_9_0.platform-tools

View file

@ -11,5 +11,6 @@
{
enable = cfg.enable;
allowedTCPPorts = cfg.allowedTCPPorts;
allowedUDPPorts = [ 53 ];
};
}

View file

@ -1,9 +1,11 @@
{ config, lib, pkgs, ... }:
let
cfg = config.profile.printing;
username = config.profile.user.name;
in
{
config = lib.mkIf cfg.enable {
users.users.${username}.extraGroups = [ "lp" ];
services.printing = {
enable = true;
drivers = [ pkgs.brlaser ]; # Brother Laser Printer

View file

@ -1,9 +1,11 @@
{ config, lib, pkgs, ... }:
let
cfg = config.profile.scanner;
username = config.profile.user.name;
in
{
config = lib.mkIf cfg.enable {
users.users.${username}.extraGroups = [ "scanner" ];
environment.systemPackages = with pkgs; [
skanlite
];

View file

@ -1,9 +1,11 @@
{ config, lib, pkgs, ... }:
let
cfg = config.profile.podman;
username = config.profile.user.name;
in
{
config = lib.mkIf cfg.enable {
users.users.${username}.extraGroups = [ "podman" ];
# services.caddy.enable = true;
environment.systemPackages = with pkgs; [
dive # look into docker image layers
@ -11,6 +13,7 @@ in
podman-compose # start group of containers for dev
];
systemd.timers."podman-auto-update".enable = true;
virtualisation.containers.enable = true;
virtualisation.oci-containers.backend = "podman";
virtualisation.podman = {
@ -21,7 +24,7 @@ in
defaultNetwork.settings.dns_enabled = true;
};
# https://madison-technologies.com/take-your-nixos-container-config-and-shove-it/
networking.firewall.interfaces.podman1 = {
networking.firewall.interfaces."podman[0-9]+" = {
allowedUDPPorts = [ 53 ]; # this needs to be there so that containers can look eachother's names up over DNS
};
};
@ -30,5 +33,6 @@ in
imports = [
./caddy.nix
./kavita.nix
./pihole.nix
];
}

90
system/podman/pihole.nix Normal file
View file

@ -0,0 +1,90 @@
{ config, lib, pkgs, ... }:
let
name = "pihole";
podman = config.profile.podman;
pihole = podman.pihole;
inherit (lib) mkIf;
gateway = "10.1.1.1";
subnet = "10.1.1.0/29";
ip = "10.1.1.3";
ip-range = "10.1.1.3/29";
image = "pihole/pihole:latest";
in
{
config = mkIf (podman.enable && pihole.enable) {
services.caddy.virtualHosts."pihole.tigor.web.id".extraConfig = ''
@root path /
redir @root /admin
reverse_proxy ${ip}:80
'';
sops.secrets."pihole/env" = {
sopsFile = ../../secrets/pihole.yaml;
};
systemd.services.create-kavita-network = {
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
wantedBy = [ "podman-pihole.service" ];
script = ''${pkgs.podman}/bin/podman network exists ${name} || ${pkgs.podman}/bin/podman network create --gateway=${gateway} --subnet=${subnet} --ip-range=${ip-range} ${name}'';
};
environment.etc."pihole/custom.list" = {
# Copy file instead of symlink
mode = "0400";
# Creates a pihole custom.list file with the following pattern:
#
# custom.list:
# 192.168.100.5 {domain_name_1}
# 192.168.100.5 {domain_name_2}
#
# For each domain defined in services.caddy.virtualHosts
text =
let
inherit (lib) strings attrsets;
in
''${strings.concatStringsSep "\n" (
attrsets.mapAttrsToList (name: _: "192.168.100.5 ${strings.removePrefix "https://" name}") config.services.caddy.virtualHosts
)}
'';
};
virtualisation.oci-containers.containers.pihole = {
inherit image;
environment = {
TZ = "Asia/Jakarta";
PIHOLE_DNS_ = "192.168.100.5";
DHCP_ACTIVE = "true";
DHCP_START = "192.168.100.20";
DHCP_END = "192.168.100.254";
DHCP_ROUTER = "192.168.100.1";
DNS_BOGUS_PRIV = "false";
DNS_FQDN_REQUIRED = "false";
};
ports = [
"192.168.100.4:53:53/udp"
"67:67/udp"
];
volumes = [
"pihole-etc:/etc/pihole"
"pihole-dnsmasq:/etc/dnsmasq.d"
"/etc/pihole/custom.list:/etc/pihole/custom.list"
];
environmentFiles = [
config.sops.secrets."pihole/env".path
];
extraOptions = [
"--ip=${ip}"
"--network=${name}"
"--cap-add=NET_ADMIN"
"--cap-add=NET_BIND_SERVICE"
"--cap-add=NET_RAW"
"--cap-add=SYS_NICE"
"--cap-add=CHOWN"
];
};
};
}

View file

@ -31,7 +31,7 @@ in
};
};
sops.secrets."runner_token" = {
sops.secrets."forgejo/runners/global" = {
sopsFile = ../../secrets/forgejo.yaml;
};
@ -42,8 +42,15 @@ in
enable = true;
name = config.networking.hostName;
url = config.services.forgejo.settings.server.ROOT_URL;
tokenFile = config.sops.secrets."runner_token".path;
tokenFile = config.sops.secrets."forgejo/runners/global".path;
settings = {
runner = {
capacity = 2;
timeout = "1h";
};
cache = {
enabled = true;
};
container = {
privileged = true;
# docker_host = "unix:///var/run/docker.sock";

View file

@ -5,13 +5,13 @@ let
in
{
config = mkIf cfg.enable {
networking.resolvconf.useLocalResolver = true;
networking.resolvconf.useLocalResolver = false;
networking.nameservers = [ "192.168.100.5" ];
services.stubby = {
enable = true;
settings = pkgs.stubby.passthru.settingsExample // {
listen_addresses = [
"0.0.0.0@53"
"0::0"
"192.168.100.5"
];
upstream_recursive_servers = [
{

View file

@ -7,7 +7,7 @@ in
users.users.${user} = {
isNormalUser = true;
description = fullName;
extraGroups = [ "networkmanager" "wheel" "docker" "adbusers" "scanner" "lp" "podman" ];
extraGroups = [ "networkmanager" "wheel" ];
shell = pkgs.zsh;
};