Mochi init
This commit is contained in:
commit
cc530d3d5f
90 changed files with 3276 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
|||
use nix
|
50
.forgejo/workflows/build.yml
Normal file
50
.forgejo/workflows/build.yml
Normal file
|
@ -0,0 +1,50 @@
|
|||
name: "Build"
|
||||
on:
|
||||
pull_request:
|
||||
jobs:
|
||||
nix-build:
|
||||
if: github.event.pull_request.draft == false
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- system: varda
|
||||
os: native-aarch64
|
||||
- system: durincore
|
||||
os: native-x86_64
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
PATH: ${{ format('{0}:{1}', '/run/current-system/sw/bin', env.PATH) }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: https://github.com/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: https://github.com/cachix/cachix-action@v15
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
name: hsndev
|
||||
# If you chose API tokens for write access OR if you have a private cache
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
# env:
|
||||
# USER: 'root'
|
||||
|
||||
- name: Garbage collect build dependencies
|
||||
run: nix-collect-garbage
|
||||
|
||||
- name: Build new ${{ matrix.system }} system
|
||||
shell: bash
|
||||
run: |
|
||||
set -o pipefail
|
||||
nix build \
|
||||
".#top.${{ matrix.system }}" \
|
||||
--profile ./profile \
|
||||
--fallback \
|
||||
-v \
|
||||
--log-format raw \
|
||||
> >(tee stdout.log) 2> >(tee /tmp/nix-build-err.log >&2)
|
||||
- name: Push to Cachix
|
||||
if: success()
|
||||
env:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
run: nix build ".#top.${{ matrix.system }}" --json | jq -r .[].drvPath | cachix push hsndev
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
**/*.tmp.sops.yaml
|
||||
**/*.sops.tmp.yaml
|
||||
age.key
|
||||
result*
|
||||
.direnv
|
||||
.kube
|
38
.pre-commit-config.yaml
Normal file
38
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
fail_fast: false
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/adrienverge/yamllint
|
||||
rev: v1.35.1
|
||||
hooks:
|
||||
- args:
|
||||
- --config-file
|
||||
- .yamllint.yaml
|
||||
id: yamllint
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: fix-byte-order-marker
|
||||
- id: mixed-line-ending
|
||||
- id: check-added-large-files
|
||||
args: [--maxkb=2048]
|
||||
- id: check-merge-conflict
|
||||
- id: check-executables-have-shebangs
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.5.5
|
||||
hooks:
|
||||
- id: remove-crlf
|
||||
- id: remove-tabs
|
||||
exclude: (Makefile)
|
||||
- repo: https://github.com/zricethezav/gitleaks
|
||||
rev: v8.18.2
|
||||
hooks:
|
||||
- id: gitleaks
|
||||
- repo: https://github.com/yuvipanda/pre-commit-hook-ensure-sops
|
||||
rev: v1.1
|
||||
hooks:
|
||||
- id: sops-encryption
|
||||
# Uncomment to exclude all markdown files from encryption
|
||||
# exclude: *.\.md
|
29
.sops.yaml
Normal file
29
.sops.yaml
Normal file
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
# config files for sops & used for encrypting keys that sops-nix decrypts.
|
||||
# each machine key is derieved from its generated `ssh_hosts_ed` file
|
||||
# via ssh-to-age
|
||||
# sops encrypts the secrets ready to decrypt with the private key of any of the below machines
|
||||
# OR my 'main' key thats kept outside this repo securely.
|
||||
|
||||
# key-per-machine is a little more secure and a little more work than
|
||||
# copying one key to each machine
|
||||
|
||||
keys:
|
||||
- users:
|
||||
- &jahanson age18kj3xhlvgjeg2awwku3r8d95w360uysu0w5ejghnp4kh8qmtge5qwa2vjp
|
||||
- hosts:
|
||||
- &durincore age1d9p83j52m2xg0vh9k7q0uwlxwhs3y6tlv68yg9s2h9mdw2fmmsqshddz5m
|
||||
- &gandalf age1nuj9sk2k8ede06f8gk5twdlc593uuc7lll2dvuy20nxw9zn97u5swrcjpj
|
||||
- &telperion age1z3vjvkead2h934n3w4m5m7tg4tj5qlzagsq6ly84h3tcu7x4ldsqd3s5fg
|
||||
- &varda age1a8z3p24v32l9yxm5z2l8h7rpc3nhacyfv4jvetk2lenrvsdstd3sdu2kaf
|
||||
|
||||
|
||||
creation_rules:
|
||||
- path_regex: .*\.sops\.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *durincore
|
||||
- *gandalf
|
||||
- *jahanson
|
||||
- *telperion
|
||||
- *varda
|
23
.taskfiles/pre-commit/Taskfile.yaml
Normal file
23
.taskfiles/pre-commit/Taskfile.yaml
Normal file
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
# yaml-language-server: $schema=https://taskfile.dev/schema.json
|
||||
version: "3"
|
||||
|
||||
vars:
|
||||
host: $HOSTNAME
|
||||
|
||||
tasks:
|
||||
|
||||
init:
|
||||
desc: Initialize pre-commit hooks
|
||||
cmds:
|
||||
- pre-commit install --install-hooks
|
||||
|
||||
update:
|
||||
desc: Update pre-commit dependencies
|
||||
cmds:
|
||||
- pre-commit autoupdate
|
||||
|
||||
run:
|
||||
desc: Run pre-commit
|
||||
cmds:
|
||||
- pre-commit run --all-files
|
18
.taskfiles/sops/Taskfile.yaml
Normal file
18
.taskfiles/sops/Taskfile.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
# yaml-language-server: $schema=https://taskfile.dev/schema.json
|
||||
version: "3"
|
||||
|
||||
tasks:
|
||||
re-encrypt:
|
||||
desc: Decrypt and re-encrypt all sops secrets
|
||||
silent: true
|
||||
dir: "{{.USER_WORKING_DIR}}"
|
||||
vars:
|
||||
SECRET_FILES:
|
||||
sh: find . -type f -name '*.sops.yaml' ! -name ".sops.yaml"
|
||||
cmds:
|
||||
- for: { var: SECRET_FILES }
|
||||
cmd: |
|
||||
echo "Re-encrypting {{ .ITEM }}"
|
||||
sops --decrypt --in-place "{{ .ITEM }}"
|
||||
sops --encrypt --in-place "{{ .ITEM }}"
|
11
.vscode/extensions.json
vendored
Normal file
11
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"jnoortheen.nix-ide",
|
||||
"mikestead.dotenv",
|
||||
"redhat.ansible",
|
||||
"redhat.vscode-yaml",
|
||||
"signageos.signageos-vscode-sops",
|
||||
"pkief.material-icon-theme",
|
||||
"ms-vscode-remote.remote-ssh"
|
||||
]
|
||||
}
|
32
.vscode/module.code-snippets
vendored
Normal file
32
.vscode/module.code-snippets
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"nix-module": {
|
||||
"prefix": "nm",
|
||||
"body": [
|
||||
"{ lib",
|
||||
", config",
|
||||
", pkgs",
|
||||
", ...",
|
||||
"}:",
|
||||
"with lib;",
|
||||
"let",
|
||||
" cfg = config.mySystem.${1}.${2};",
|
||||
" app = \"${3}\"",
|
||||
" appFolder = \"apps/${app}\";",
|
||||
" persistentFolder = \"${config.mySystem.persistentFolder}/${appFolder}\";",
|
||||
" user = app;",
|
||||
" group = app;",
|
||||
"in",
|
||||
"{",
|
||||
" options.mySystem.${1}.${2}.enable = mkEnableOption \"${4}\";",
|
||||
"",
|
||||
" config = mkIf cfg.enable {",
|
||||
"",
|
||||
" $5",
|
||||
"",
|
||||
" };",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"description": "nix-module"
|
||||
}
|
||||
}
|
27
.yamllint.yaml
Normal file
27
.yamllint.yaml
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
ignore: |
|
||||
.direnv/
|
||||
.private/
|
||||
.vscode/
|
||||
*.sops.*
|
||||
|
||||
extends: default
|
||||
|
||||
rules:
|
||||
truthy:
|
||||
allowed-values: ["true", "false", "on"]
|
||||
|
||||
comments:
|
||||
min-spaces-from-content: 1
|
||||
|
||||
line-length: disable
|
||||
|
||||
braces:
|
||||
min-spaces-inside: 0
|
||||
max-spaces-inside: 1
|
||||
|
||||
brackets:
|
||||
min-spaces-inside: 0
|
||||
max-spaces-inside: 0
|
||||
|
||||
indentation: enable
|
23
README.md
Normal file
23
README.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# jahanson's homelab
|
||||
|
||||
## Goals
|
||||
|
||||
- [ ] Learn nix
|
||||
- [ ] Services I want to separate from my kubernetes cluster I will use Nix.
|
||||
- [ ] Approval-based update automation for flakes.
|
||||
- [ ] Expand usage to other shell environments such as WSL, etc
|
||||
- [ ] keep it simple, use trusted boring tools
|
||||
|
||||
## TODO
|
||||
|
||||
- [ x ] Forgejo Actions
|
||||
- [ ] Bring over hosts
|
||||
- [ x ] Varda (forgejo)
|
||||
- [ ] Telperion (network services)
|
||||
- [ ] Gandalf (NixNAS)
|
||||
- [ x ] Thinkpad T470
|
||||
|
||||
## Links & References
|
||||
|
||||
- [truxnell/dotfiles](https://github.com//truxnell/nix-config/)
|
||||
- [billimek/dotfiles](https://github.com/billimek/dotfiles/)
|
33
Taskfile.yaml
Normal file
33
Taskfile.yaml
Normal file
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
# go-task runner file - rest of config in .taskfiles/**.*.yaml
|
||||
version: "3"
|
||||
|
||||
includes:
|
||||
sops:
|
||||
taskfile: ".taskfiles/sops"
|
||||
dir: .taskfiles/sops
|
||||
pre:
|
||||
taskfile: ".taskfiles/pre-commit"
|
||||
dir: "{{.ROOT_DOR}}"
|
||||
|
||||
tasks:
|
||||
default:
|
||||
silent: true
|
||||
cmds:
|
||||
- task -l
|
||||
|
||||
lint:
|
||||
desc: Run statix lint
|
||||
cmds:
|
||||
- statix check .
|
||||
|
||||
check:
|
||||
desc: Check project files
|
||||
cmds:
|
||||
- task: lint
|
||||
- task: pc-run
|
||||
|
||||
format:
|
||||
desc: Check project files
|
||||
cmds:
|
||||
- nixpkgs-fmt {{.ROOT_DIR}}
|
0
flake.nix
Normal file
0
flake.nix
Normal file
93
nixos/home/jahanson/global.nix
Normal file
93
nixos/home/jahanson/global.nix
Normal file
|
@ -0,0 +1,93 @@
|
|||
{ pkgs, config, ... }:
|
||||
with config;
|
||||
{
|
||||
imports = [
|
||||
../modules
|
||||
];
|
||||
|
||||
config = {
|
||||
myHome.username = "jahanson";
|
||||
myHome.homeDirectory = "/home/jahanson/";
|
||||
|
||||
systemd.user.sessionVariables = {
|
||||
EDITOR = "vim";
|
||||
};
|
||||
|
||||
home = {
|
||||
# Install these packages for my user
|
||||
packages = with pkgs; [
|
||||
# misc
|
||||
file
|
||||
which
|
||||
tree
|
||||
gnused
|
||||
gnutar
|
||||
gawk
|
||||
zstd
|
||||
gnupg
|
||||
|
||||
# archives
|
||||
zip
|
||||
xz
|
||||
unzip
|
||||
p7zip
|
||||
|
||||
# cli
|
||||
_1password
|
||||
bat
|
||||
dbus
|
||||
direnv
|
||||
git
|
||||
nix-index
|
||||
python3
|
||||
fzf
|
||||
ripgrep
|
||||
vim
|
||||
lsd
|
||||
|
||||
# terminal file managers
|
||||
nnn
|
||||
ranger
|
||||
yazi
|
||||
|
||||
# networking tools
|
||||
iperf3
|
||||
dnsutils # `dig` + `nslookup`
|
||||
ldns # replacement of `dig`, it provide the command `drill`
|
||||
aria2 # A lightweight multi-protocol & multi-source command-line download utility
|
||||
socat # replacement of openbsd-netcat
|
||||
nmap # A utility for network discovery and security auditing
|
||||
ipcalc # it is a calculator for the IPv4/v6 addresses
|
||||
|
||||
# system tools
|
||||
sysstat
|
||||
lm_sensors # for `sensors` command
|
||||
ethtool
|
||||
pciutils # lspci
|
||||
usbutils # lsusb
|
||||
|
||||
# system call monitoring
|
||||
strace # system call monitoring
|
||||
ltrace # library call monitoring
|
||||
lsof # list open files
|
||||
|
||||
btop # replacement of htop/nmon
|
||||
iotop # io monitoring
|
||||
iftop # network monitoring
|
||||
|
||||
# dev utils
|
||||
direnv # shell environment management
|
||||
envsubst
|
||||
|
||||
# nix tools
|
||||
nvd
|
||||
];
|
||||
|
||||
sessionVariables = {
|
||||
EDITOR = "vim";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
}
|
6
nixos/home/jahanson/server.nix
Normal file
6
nixos/home/jahanson/server.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./global.nix
|
||||
];
|
||||
}
|
42
nixos/home/jahanson/workstation.nix
Normal file
42
nixos/home/jahanson/workstation.nix
Normal file
|
@ -0,0 +1,42 @@
|
|||
{ pkgs, config, ... }:
|
||||
with config;
|
||||
{
|
||||
imports = [
|
||||
./global.nix
|
||||
];
|
||||
|
||||
myHome.programs.firefox.enable = true;
|
||||
|
||||
myHome.shell = {
|
||||
starship.enable = true;
|
||||
fish.enable = true;
|
||||
|
||||
git = {
|
||||
enable = true;
|
||||
username = "Joseph Hanson";
|
||||
email = "joe@veri.dev";
|
||||
signingKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIDSAmssproxG+KsVn2DfuteBAemHrmmAFzCtldpKl4J";
|
||||
};
|
||||
};
|
||||
|
||||
home = {
|
||||
# Install these packages for my user
|
||||
packages = with pkgs;
|
||||
[
|
||||
#apps
|
||||
_1password-gui
|
||||
discord
|
||||
flameshot
|
||||
vlc
|
||||
|
||||
# cli
|
||||
brightnessctl
|
||||
|
||||
# dev utils
|
||||
pre-commit # Pre-commit tasks for git
|
||||
minio-client # S3 management
|
||||
shellcheck # shell script linting
|
||||
];
|
||||
|
||||
};
|
||||
}
|
36
nixos/home/modules/default.nix
Normal file
36
nixos/home/modules/default.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{ lib, ... }: {
|
||||
|
||||
imports = [
|
||||
./shell
|
||||
./programs
|
||||
./security
|
||||
];
|
||||
|
||||
options.myHome.username = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "users username";
|
||||
default = "jahanson";
|
||||
};
|
||||
options.myHome.homeDirectory = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "users homedir";
|
||||
default = "jahanson";
|
||||
};
|
||||
|
||||
# Home-manager defaults
|
||||
config = {
|
||||
home.stateVersion = "24.11";
|
||||
|
||||
programs = {
|
||||
home-manager.enable = true;
|
||||
git.enable = true;
|
||||
};
|
||||
|
||||
xdg.enable = true;
|
||||
|
||||
nixpkgs.config = {
|
||||
allowUnfree = true;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
5
nixos/home/modules/programs/browsers/default.nix
Normal file
5
nixos/home/modules/programs/browsers/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{ ... }: {
|
||||
imports = [
|
||||
./firefox
|
||||
];
|
||||
}
|
32
nixos/home/modules/programs/browsers/firefox/default.nix
Normal file
32
nixos/home/modules/programs/browsers/firefox/default.nix
Normal file
|
@ -0,0 +1,32 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.myHome.programs.firefox;
|
||||
in
|
||||
{
|
||||
options.myHome.programs.firefox.enable = mkEnableOption "Firefox";
|
||||
|
||||
config = mkIf cfg.enable
|
||||
{
|
||||
programs.firefox = {
|
||||
enable = true;
|
||||
package = pkgs.firefox.override
|
||||
{
|
||||
extraPolicies = {
|
||||
DontCheckDefaultBrowser = true;
|
||||
DisablePocket = true;
|
||||
# See nixpkgs' firefox/wrapper.nix to check which options you can use
|
||||
nativeMessagingHosts = [
|
||||
# Gnome shell native connector
|
||||
pkgs.gnome-browser-connector
|
||||
# plasma connector
|
||||
# plasma5Packages.plasma-browser-integration
|
||||
];
|
||||
};
|
||||
};
|
||||
policies = import ./policies.nix;
|
||||
|
||||
profiles.default = import ./profile-default.nix { inherit pkgs; };
|
||||
};
|
||||
};
|
||||
}
|
20
nixos/home/modules/programs/browsers/firefox/policies.nix
Normal file
20
nixos/home/modules/programs/browsers/firefox/policies.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
DisableTelemetry = true;
|
||||
DisableFirefoxStudies = true;
|
||||
EnableTrackingProtection = {
|
||||
Value = true;
|
||||
Locked = true;
|
||||
Cryptomining = true;
|
||||
Fingerprinting = true;
|
||||
};
|
||||
DisablePocket = true;
|
||||
# DisableFirefoxAccounts = true;
|
||||
# DisableAccounts = true;
|
||||
# DisableFirefoxScreenshots = true;
|
||||
# OverrideFirstRunPage = "";
|
||||
OverridePostUpdatePage = "";
|
||||
DontCheckDefaultBrowser = true;
|
||||
DisplayBookmarksToolbar = "never"; # alternatives: "always" or "newtab"
|
||||
DisplayMenuBar = "default-off"; # alternatives: "always", "never" or "default-on"
|
||||
SearchBar = "unified"; # alternative: "separate"
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{ pkgs }:
|
||||
{
|
||||
id = 0;
|
||||
name = "default";
|
||||
isDefault = true;
|
||||
settings = {
|
||||
"browser.startup.homepage" = "https://status.hsn.dev";
|
||||
"browser.search.suggest.enabled.private" = false;
|
||||
# 0 => blank page
|
||||
# 1 => your home page(s) {default}
|
||||
# 2 => the last page viewed in Firefox
|
||||
# 3 => previous session windows and tabs
|
||||
"browser.startup.page" = "3";
|
||||
|
||||
"browser.send_pings" = false;
|
||||
# Do not track
|
||||
"privacy.donottrackheader.enabled" = "true";
|
||||
"privacy.donottrackheader.value" = 1;
|
||||
"browser.display.use_system_colors" = "true";
|
||||
|
||||
"browser.display.use_document_colors" = "false";
|
||||
"devtools.theme" = "dark";
|
||||
|
||||
"extensions.pocket.enabled" = false;
|
||||
};
|
||||
extensions = with pkgs.nur.repos.rycee.firefox-addons; [
|
||||
ublock-origin
|
||||
privacy-badger
|
||||
link-cleaner
|
||||
refined-github
|
||||
];
|
||||
}
|
5
nixos/home/modules/programs/de/default.nix
Normal file
5
nixos/home/modules/programs/de/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{ ... }: {
|
||||
imports = [
|
||||
./gnome
|
||||
];
|
||||
}
|
36
nixos/home/modules/programs/de/gnome/default.nix
Normal file
36
nixos/home/modules/programs/de/gnome/default.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Adjusted manually from generated output of dconf2nix
|
||||
# https://github.com/gvolpe/dconf2nix
|
||||
{ lib, pkgs, osConfig, ... }:
|
||||
with lib.hm.gvariant; {
|
||||
config = lib.mkIf osConfig.mySystem.de.gnome.enable {
|
||||
# add user packages
|
||||
home.packages = with pkgs; [
|
||||
dconf2nix
|
||||
];
|
||||
|
||||
# worked out from dconf2nix
|
||||
# dconf dump / | dconf2nix > dconf.nix
|
||||
# can also dconf watch
|
||||
dconf.settings = {
|
||||
"org/gnome/mutter" = {
|
||||
edge-tiling = true;
|
||||
workspaces-only-on-primary = false;
|
||||
};
|
||||
"org/gnome/desktop/wm/preferences" = {
|
||||
workspace-names = [ "sys" "talk" "web" "edit" "run" ];
|
||||
};
|
||||
"org/gnome/shell" = {
|
||||
disabled-extensions = [ "apps-menu@gnome-shell-extensions.gcampax.github.com" "light-style@gnome-shell-extensions.gcampax.github.com" "places-menu@gnome-shell-extensions.gcampax.github.com" "drive-menu@gnome-shell-extensions.gcampax.github.com" "window-list@gnome-shell-extensions.gcampax.github.com" "workspace-indicator@gnome-shell-extensions.gcampax.github.com" ];
|
||||
enabled-extensions = [ "appindicatorsupport@rgcjonas.gmail.com" "caffeine@patapon.info" "dash-to-dock@micxgx.gmail.com" "gsconnect@andyholmes.github.io" "Vitals@CoreCoding.com" "sp-tray@sp-tray.esenliyim.github.com" ];
|
||||
favorite-apps = [ "org.gnome.Nautilus.desktop" "firefox.desktop" "org.wezfurlong.wezterm.desktop" "PrusaGcodeviewer.desktop" "spotify.desktop" "org.gnome.Console.desktop" "codium.desktop" "discord.desktop" ];
|
||||
};
|
||||
"org/gnome/nautilus/preferences" = {
|
||||
default-folder-viewer = "list-view";
|
||||
};
|
||||
"org/gnome/nautilus/icon-view" = {
|
||||
default-zoom-level = "small";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
}
|
6
nixos/home/modules/programs/default.nix
Normal file
6
nixos/home/modules/programs/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{ ... }: {
|
||||
imports = [
|
||||
./browsers
|
||||
./de
|
||||
];
|
||||
}
|
5
nixos/home/modules/security/default.nix
Normal file
5
nixos/home/modules/security/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{ ... }: {
|
||||
imports = [
|
||||
./ssh
|
||||
];
|
||||
}
|
21
nixos/home/modules/security/ssh/default.nix
Normal file
21
nixos/home/modules/security/ssh/default.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ config, lib, ... }:
|
||||
with lib; let
|
||||
cfg = config.myHome.security.ssh;
|
||||
in
|
||||
{
|
||||
options.myHome.security.ssh = {
|
||||
enable = mkEnableOption "ssh";
|
||||
matchBlocks = mkOption {
|
||||
type = types.attrs;
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.ssh = {
|
||||
inherit (cfg) matchBlocks;
|
||||
enable = true;
|
||||
# addKeysToAgent = "yes";
|
||||
};
|
||||
};
|
||||
}
|
8
nixos/home/modules/shell/default.nix
Normal file
8
nixos/home/modules/shell/default.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{ ... }: {
|
||||
imports = [
|
||||
./fish
|
||||
./starship
|
||||
./wezterm
|
||||
./git
|
||||
];
|
||||
}
|
75
nixos/home/modules/shell/fish/default.nix
Normal file
75
nixos/home/modules/shell/fish/default.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
with lib; let
|
||||
inherit (config.myHome) username homeDirectory;
|
||||
cfg = config.myHome.shell.fish;
|
||||
in
|
||||
{
|
||||
options.myHome.shell.fish = {
|
||||
enable = mkEnableOption "fish";
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf cfg.enable {
|
||||
programs.fish = {
|
||||
enable = true;
|
||||
|
||||
shellAliases = {
|
||||
m = "less";
|
||||
ls = "${pkgs.lsd}/bin/lsd";
|
||||
ll = "${pkgs.lsd}/bin/lsd -l";
|
||||
la = "${pkgs.lsd}/bin/lsd -a";
|
||||
lt = "${pkgs.lsd}/bin/lsd --tree";
|
||||
lla = "${pkgs.lsd}/bin/lsd -la";
|
||||
tm = "tmux attach -t (basename $PWD) || tmux new -s (basename $PWD)";
|
||||
x = "exit";
|
||||
};
|
||||
|
||||
shellAbbrs = {
|
||||
nrs = "sudo nixos-rebuild switch --flake .";
|
||||
nvdiff = "nvd diff /run/current-system result";
|
||||
};
|
||||
|
||||
interactiveShellInit = ''
|
||||
# Erase fish_mode_prompt function
|
||||
functions -e fish_mode_prompt
|
||||
|
||||
function remove_path
|
||||
if set -l index (contains -i $argv[1] $PATH)
|
||||
set --erase --universal fish_user_paths[$index]
|
||||
end
|
||||
end
|
||||
|
||||
function update_path
|
||||
if test -d $argv[1]
|
||||
fish_add_path -m $argv[1]
|
||||
else
|
||||
remove_path $argv[1]
|
||||
end
|
||||
end
|
||||
|
||||
# Paths are in reverse priority order
|
||||
update_path /opt/homebrew/opt/postgresql@16/bin
|
||||
update_path /opt/homebrew/bin
|
||||
update_path ${homeDirectory}/.krew/bin
|
||||
update_path /nix/var/nix/profiles/default/bin
|
||||
update_path /run/current-system/sw/bin
|
||||
update_path /etc/profiles/per-user/${username}/bin
|
||||
update_path /run/wrappers/bin
|
||||
update_path ${homeDirectory}/.nix-profile/bin
|
||||
update_path ${homeDirectory}/go/bin
|
||||
update_path ${homeDirectory}/.cargo/bin
|
||||
update_path ${homeDirectory}/.local/bin
|
||||
|
||||
set -gx EDITOR "vim"
|
||||
|
||||
set -gx LSCOLORS "Gxfxcxdxbxegedabagacad"
|
||||
set -gx LS_COLORS 'di=01;34:ln=01;36:pi=33:so=01;35:bd=01;33:cd=33:or=31:ex=01;32:*.7z=01;31:*.bz2=01;31:*.gz=01;31:*.lz=01;31:*.lzma=01;31:*.lzo=01;31:*.rar=01;31:*.tar=01;31:*.tbz=01;31:*.tgz=01;31:*.xz=01;31:*.zip=01;31:*.zst=01;31:*.zstd=01;31:*.bmp=01;35:*.tiff=01;35:*.tif=01;35:*.TIFF=01;35:*.gif=01;35:*.jpeg=01;35:*.jpg=01;35:*.png=01;35:*.webp=01;35:*.pot=01;35:*.pcb=01;35:*.gbr=01;35:*.scm=01;35:*.xcf=01;35:*.spl=01;35:*.stl=01;35:*.dwg=01;35:*.ply=01;35:*.apk=01;31:*.deb=01;31:*.rpm=01;31:*.jad=01;31:*.jar=01;31:*.crx=01;31:*.xpi=01;31:*.avi=01;35:*.divx=01;35:*.m2v=01;35:*.m4v=01;35:*.mkv=01;35:*.MOV=01;35:*.mov=01;35:*.mp4=01;35:*.mpeg=01;35:*.mpg=01;35:*.sample=01;35:*.wmv=01;35:*.3g2=01;35:*.3gp=01;35:*.gp3=01;35:*.webm=01;35:*.flv=01;35:*.ogv=01;35:*.f4v=01;35:*.3ga=01;35:*.aac=01;35:*.m4a=01;35:*.mp3=01;35:*.mp4a=01;35:*.oga=01;35:*.ogg=01;35:*.opus=01;35:*.s3m=01;35:*.sid=01;35:*.wma=01;35:*.flac=01;35:*.alac=01;35:*.mid=01;35:*.midi=01;35:*.pcm=01;35:*.wav=01;35:*.ass=01;33:*.srt=01;33:*.ssa=01;33:*.sub=01;33:*.git=01;33:*.ass=01;33:*README=33:*README.rst=33:*README.md=33:*LICENSE=33:*COPYING=33:*INSTALL=33:*COPYRIGHT=33:*AUTHORS=33:*HISTORY=33:*CONTRIBUTOS=33:*PATENTS=33:*VERSION=33:*NOTICE=33:*CHANGES=33:*CHANGELOG=33:*log=33:*.txt=33:*.md=33:*.markdown=33:*.nfo=33:*.org=33:*.pod=33:*.rst=33:*.tex=33:*.texttile=33:*.bib=35:*.json=35:*.jsonl=35:*.jsonnet=35:*.libsonnet=35:*.rss=35:*.xml=35:*.fxml=35:*.toml=35:*.yaml=35:*.yml=35:*.dtd=35:*.cbr=35:*.cbz=35:*.chm=35:*.pdf=35:*.PDF=35:*.epub=35:*.awk=35:*.bash=35:*.bat=35:*.BAT=35:*.sed=35:*.sh=35:*.zsh=35:*.vim=35:*.py=35:*.ipynb=35:*.rb=35:*.gemspec=35:*.pl=35:*.PL=35:*.t=35:*.msql=35:*.mysql=35:*.pgsql=35:*.sql=35:*.r=35:*.R=35:*.cljw=35:*.scala=35:*.sc=35:*.dart=35:*.asm=35:*.cl=35:*.lisp=35:*.rkt=35:*.el=35:*.elc=35:*.eln=35:*.lua=35:*.c=35:*.C=35:*.h=35:*.H=35:*.tcc=35:*.c++=35:*.h++=35:*.hpp=35:*.hxx=35:*ii.=35:*.m=35:*.M=35:*.cc=35:*.cs=35:*.cp=35:*.cpp=35:*.cxx=35:*.go=35:*.f=35:*.F=35:*.nim=35:*.nimble=35:*.s=35:*.S=35:*.rs=35:*.scpt=35:*.swift=35:*.vala=35:*.vapi=35:*.hs=35:*.lhs=35:*.zig=35:*.v=35:*.pyc=35:*.tf=35:*.tfstate=35:*.tfvars=35:*.css=35:*.less=35:*.sass=35:*.scss=35:*.htm=35:*.html=35:*.jhtm=35:*.mht=35:*.eml=35:*.coffee=35:*.java=35:*.js=35:*.mjs=35:*.jsm=35:*.jsp=35:*.rasi=35:*.php=35:*.twig=35:*.vb=35:*.vba=35:*.vbs=35:*.Dockerfile=35:*.dockerignore=35:*.Makefile=35:*.MANIFEST=35:*.am=35:*.in=35:*.hin=35:*.scan=35:*.m4=35:*.old=35:*.out=35:*.SKIP=35:*.diff=35:*.patch=35:*.tmpl=35:*.j2=35:*PKGBUILD=35:*config=35:*.conf=35:*.service=31:*.@.service=31:*.socket=31:*.swap=31:*.device=31:*.mount=31:*.automount=31:*.target=31:*.path=31:*.timer=31:*.snapshot=31:*.allow=31:*.swp=31:*.swo=31:*.tmp=31:*.pid=31:*.state=31:*.lock=31:*.lockfile=31:*.pacnew=31:*.un=31:*.orig=31:'
|
||||
'';
|
||||
};
|
||||
|
||||
home.sessionVariables.fish_greeting = "";
|
||||
|
||||
programs.nix-index.enable = true;
|
||||
})
|
||||
];
|
||||
}
|
69
nixos/home/modules/shell/git/default.nix
Normal file
69
nixos/home/modules/shell/git/default.nix
Normal file
|
@ -0,0 +1,69 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
let
|
||||
cfg = config.myHome.shell.git;
|
||||
in
|
||||
{
|
||||
options.myHome.shell.git = {
|
||||
enable = lib.mkEnableOption "git";
|
||||
username = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
email = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
signingKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.enable {
|
||||
programs.gh.enable = true;
|
||||
programs.gpg.enable = true;
|
||||
|
||||
programs.git = {
|
||||
enable = true;
|
||||
|
||||
userName = cfg.username;
|
||||
userEmail = cfg.email;
|
||||
|
||||
extraConfig = {
|
||||
core.autocrlf = "input";
|
||||
init.defaultBranch = "main";
|
||||
pull.rebase = true;
|
||||
rebase.autoStash = true;
|
||||
# public key for signing commits
|
||||
user.signingKey = cfg.signingKey;
|
||||
# ssh instead of gpg
|
||||
gpg.format = "ssh";
|
||||
# 1password signing gui git signing
|
||||
gpg.ssh.program = "${pkgs._1password-gui}/bin/op-ssh-sign";
|
||||
# Auto sign commits without -S
|
||||
commit.gpgsign = true;
|
||||
};
|
||||
aliases = {
|
||||
co = "checkout";
|
||||
};
|
||||
ignores = [
|
||||
# Mac OS X hidden files
|
||||
".DS_Store"
|
||||
# Windows files
|
||||
"Thumbs.db"
|
||||
# asdf
|
||||
".tool-versions"
|
||||
# Sops
|
||||
".decrypted~*"
|
||||
"*.decrypted.*"
|
||||
# Python virtualenvs
|
||||
".venv"
|
||||
];
|
||||
};
|
||||
|
||||
home.packages = [
|
||||
pkgs.git-filter-repo
|
||||
pkgs.tig
|
||||
pkgs.lazygit
|
||||
];
|
||||
})
|
||||
];
|
||||
}
|
115
nixos/home/modules/shell/starship/default.nix
Normal file
115
nixos/home/modules/shell/starship/default.nix
Normal file
|
@ -0,0 +1,115 @@
|
|||
{ lib
|
||||
, config
|
||||
, ...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.myHome.shell.starship;
|
||||
in
|
||||
{
|
||||
options.myHome.shell.starship = { enable = mkEnableOption "starship"; };
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.starship = {
|
||||
enable = true;
|
||||
settings = {
|
||||
add_newline = false;
|
||||
command_timeout = 1000;
|
||||
format = lib.concatStrings [
|
||||
"$username"
|
||||
"$hostname"
|
||||
"$directory"
|
||||
"$git_branch"
|
||||
"$git_status"
|
||||
"$\{custom.direnv\}"
|
||||
"$fill"
|
||||
"$python"
|
||||
"$status"
|
||||
"$cmd_duration"
|
||||
"$line_break"
|
||||
"$character"
|
||||
];
|
||||
|
||||
username = {
|
||||
style_user = "yellow";
|
||||
style_root = "red";
|
||||
format = "[$user]($style)";
|
||||
show_always = false;
|
||||
};
|
||||
|
||||
hostname = {
|
||||
ssh_only = true;
|
||||
format = "[@$hostname]($style) in ";
|
||||
style = "green";
|
||||
};
|
||||
|
||||
directory = {
|
||||
truncation_length = 3;
|
||||
format = "[$path]($style)[$read_only]($read_only_style) ";
|
||||
style = "blue";
|
||||
read_only = " ";
|
||||
truncation_symbol = "../";
|
||||
truncate_to_repo = true;
|
||||
fish_style_pwd_dir_length = 1;
|
||||
};
|
||||
|
||||
git_branch = {
|
||||
format = "on [$symbol$branch]($style) ";
|
||||
style = "purple";
|
||||
symbol = " ";
|
||||
};
|
||||
|
||||
git_status = {
|
||||
format = "([$all_status$ahead_behind]($style) )";
|
||||
style = "purple";
|
||||
conflicted = " ";
|
||||
ahead = " ";
|
||||
behind = " ";
|
||||
diverged = " ";
|
||||
up_to_date = " ";
|
||||
untracked = " ";
|
||||
stashed = " ";
|
||||
modified = " ";
|
||||
staged = " ";
|
||||
renamed = " ";
|
||||
deleted = " ";
|
||||
};
|
||||
|
||||
fill = {
|
||||
symbol = " ";
|
||||
};
|
||||
|
||||
python = {
|
||||
format = "[\${symbol}\${pyenv_prefix}(\${version} )(\($virtualenv\) )]($style)";
|
||||
symbol = "🐍 ";
|
||||
};
|
||||
|
||||
status = {
|
||||
disabled = false;
|
||||
format = "[$symbol]($style) ";
|
||||
symbol = " ";
|
||||
success_symbol = " ";
|
||||
style = "red";
|
||||
};
|
||||
|
||||
cmd_duration = {
|
||||
min_time = 2000;
|
||||
format = "took [$duration]($style) ";
|
||||
style = "yellow";
|
||||
};
|
||||
|
||||
character = {
|
||||
success_symbol = "[](green)";
|
||||
error_symbol = "[](green)";
|
||||
vicmd_symbol = "[](purple)";
|
||||
};
|
||||
|
||||
custom.direnv = {
|
||||
format = "[$symbol]($style)";
|
||||
symbol = " ";
|
||||
style = "blue";
|
||||
when = "env | grep -E '^DIRENV_FILE='";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
43
nixos/home/modules/shell/wezterm/default.nix
Normal file
43
nixos/home/modules/shell/wezterm/default.nix
Normal file
|
@ -0,0 +1,43 @@
|
|||
{ config
|
||||
, pkgs
|
||||
, lib
|
||||
, ...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.myHome.shell.wezterm;
|
||||
in
|
||||
{
|
||||
options.myHome.shell.wezterm = {
|
||||
enable = mkEnableOption "wezterm";
|
||||
configPath = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# xdg.configFile."wezterm/wezterm.lua".source = config.lib.file.mkOutOfStoreSymlink cfg.configPath;
|
||||
programs.wezterm.package = pkgs.unstable.wezterm;
|
||||
programs.wezterm = {
|
||||
enable = true;
|
||||
extraConfig = ''
|
||||
local wez = require('wezterm')
|
||||
return {
|
||||
-- issue relating to nvidia drivers
|
||||
-- https://github.com/wez/wezterm/issues/2011
|
||||
-- had to build out 550.67 manually to 'fix'
|
||||
enable_wayland = true,
|
||||
|
||||
color_scheme = "Dracula (Official)",
|
||||
check_for_updates = false,
|
||||
window_background_opacity = .90,
|
||||
window_padding = {
|
||||
left = '2cell',
|
||||
right = '2cell',
|
||||
top = '1cell',
|
||||
bottom = '0cell',
|
||||
},
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
33
nixos/hosts/durincore/default.nix
Normal file
33
nixos/hosts/durincore/default.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{ ... }: {
|
||||
config = {
|
||||
|
||||
# hardware-configuration.nix - half of the hardware-configuration.nix file
|
||||
|
||||
networking.hostId = "ad4380db";
|
||||
networking.hostName = "durincore";
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "rpool/root";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home" =
|
||||
{ device = "rpool/home";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/F1B9-CA7C";
|
||||
fsType = "vfat";
|
||||
options = [ "fmask=0077" "dmask=0077" ];
|
||||
};
|
||||
|
||||
swapDevices = [ ];
|
||||
|
||||
# System settings and services.
|
||||
mySystem = {
|
||||
system.motd.networkInterfaces = [ "enp0s31f6" "wlp4s0" ];
|
||||
};
|
||||
|
||||
};
|
||||
}
|
34
nixos/hosts/varda/default.nix
Normal file
34
nixos/hosts/varda/default.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{ ... }: {
|
||||
imports = [ ];
|
||||
|
||||
networking.hostId = "cdab8473";
|
||||
networking.hostName = "varda"; # Define your hostname.
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "rpool/root";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home" = {
|
||||
device = "rpool/home";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/8091-E7F2";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices = [ ];
|
||||
|
||||
# System settings and services.
|
||||
mySystem = {
|
||||
system.motd.networkInterfaces = [ "enp1s0" ];
|
||||
security.acme.enable = true;
|
||||
services = {
|
||||
forgejo.enable = true;
|
||||
nginx.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
43
nixos/lib/default.nix
Normal file
43
nixos/lib/default.nix
Normal file
|
@ -0,0 +1,43 @@
|
|||
{ lib, ... }:
|
||||
|
||||
with lib;
|
||||
rec {
|
||||
|
||||
firstOrDefault = first: default: if first != null then first else default;
|
||||
existsOrDefault = x: set: default: if builtins.hasAttr x set then builtins.getAttr x set else default;
|
||||
|
||||
# main service builder
|
||||
mkService = options: (
|
||||
let
|
||||
user = existsOrDefault "user" options "568";
|
||||
group = existsOrDefault "group" options "568";
|
||||
|
||||
enableBackups = (lib.attrsets.hasAttrByPath [ "persistence" "folder" ] options)
|
||||
&& (lib.attrsets.attrByPath [ "persistence" "enable" ] true options);
|
||||
|
||||
# Security options for containers
|
||||
containerExtraOptions = lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "privileged" ] false options) [ "--privileged" ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "readOnly" ] false options) [ "--read-only" ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "tmpfs" ] false options) [ (map (folders: "--tmpfs=${folders}") tmpfsFolders) ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "noNewPrivileges" ] false options) [ "--security-opt=no-new-privileges" ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "dropAll" ] false options) [ "--cap-drop=ALL" ]
|
||||
;
|
||||
in
|
||||
{
|
||||
virtualisation.oci-containers.containers.${options.app} = mkIf options.container.enable {
|
||||
image = "${options.container.image}";
|
||||
user = "${user}:${group}";
|
||||
environment = {
|
||||
TZ = options.timeZone;
|
||||
} // options.container.env;
|
||||
environmentFiles = lib.attrsets.attrByPath [ "container" "envFiles" ] [ ] options;
|
||||
volumes = [ "/etc/localtime:/etc/localtime:ro" ] ++
|
||||
lib.optionals (lib.attrsets.hasAttrByPath [ "container" "persistentFolderMount" ] options) [
|
||||
"${options.persistence.folder}:${options.container.persistentFolderMount}:rw"
|
||||
] ++ lib.attrsets.attrByPath [ "container" "volumes" ] [ ] options;
|
||||
extraOptions = containerExtraOptions;
|
||||
};
|
||||
systemd.tmpfiles.rules = lib.optionals (lib.attrsets.hasAttrByPath [ "persistence" "folder" ] options) [ "d ${options.persistence.folder} 0750 ${user} ${group} -" ];
|
||||
}
|
||||
);
|
||||
}
|
0
nixos/modules/.gitkeep
Normal file
0
nixos/modules/.gitkeep
Normal file
9
nixos/modules/README.md
Normal file
9
nixos/modules/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
## Modules
|
||||
|
||||
A set of 'custom' modules with the aim to enable easy on/off/settings to build up a system modularly to my 'specs'.
|
||||
|
||||
The main goal is to build up a `mySystem` options key which is easy to read and toggle functionality on and off.
|
||||
|
||||
This option key will largely be manipulated by a profile to build up a host to a base, then toggle specific options from there.
|
||||
|
||||
I will _try_ and only do modules for things I want to be able to configure, and just use nixos config directly for some simple static things.
|
3
nixos/modules/default.nix
Normal file
3
nixos/modules/default.nix
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
mySystem = import ./nixos;
|
||||
}
|
56
nixos/modules/nixos/containers/backrest/default.nix
Normal file
56
nixos/modules/nixos/containers/backrest/default.nix
Normal file
|
@ -0,0 +1,56 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
app = "backrest";
|
||||
image = "garethgeorge/backrest:v1.1.0";
|
||||
user = "568"; #string
|
||||
group = "568"; #string
|
||||
port = 9898; #int
|
||||
cfg = config.mySystem.services.${app};
|
||||
appFolder = "/var/lib/${app}";
|
||||
# persistentFolder = "${config.mySystem.persistentFolder}/var/lib/${appFolder}";
|
||||
in
|
||||
{
|
||||
options.mySystem.services.${app} =
|
||||
{
|
||||
enable = mkEnableOption "${app}";
|
||||
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# ensure folder exist and has correct owner/group
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${appFolder}/config 0750 ${user} ${group} -"
|
||||
"d ${appFolder}/data 0750 ${user} ${group} -"
|
||||
"d ${appFolder}/cache 0750 ${user} ${group} -"
|
||||
];
|
||||
|
||||
virtualisation.oci-containers.containers.${app} = {
|
||||
image = "${image}";
|
||||
user = "${user}:${group}";
|
||||
environment = {
|
||||
BACKREST_PORT = "9898";
|
||||
BACKREST_DATA = "/data";
|
||||
BACKREST_CONFIG = "/config/config.json";
|
||||
XDG_CACHE_HOME = "/cache";
|
||||
};
|
||||
volumes = [
|
||||
"${appFolder}/nixos/config:/config:rw"
|
||||
"${appFolder}/nixos/data:/data:rw"
|
||||
"${appFolder}/nixos/cache:/cache:rw"
|
||||
"${config.mySystem.nasFolder}/backup/nixos/nixos:/repos:rw"
|
||||
"/etc/localtime:/etc/localtime:ro"
|
||||
];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||
useACMEHost = config.networking.domain;
|
||||
forceSSL = true;
|
||||
locations."^~ /" = {
|
||||
proxyPass = "http://${app}:${builtins.toString port}";
|
||||
extraConfig = "resolver 10.88.0.1;";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
5
nixos/modules/nixos/containers/default.nix
Normal file
5
nixos/modules/nixos/containers/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./backrest
|
||||
];
|
||||
}
|
5
nixos/modules/nixos/de/default.nix
Normal file
5
nixos/modules/nixos/de/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./gnome.nix
|
||||
];
|
||||
}
|
101
nixos/modules/nixos/de/gnome.nix
Normal file
101
nixos/modules/nixos/de/gnome.nix
Normal file
|
@ -0,0 +1,101 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.de.gnome;
|
||||
in
|
||||
{
|
||||
options.mySystem.de.gnome.enable = mkEnableOption "GNOME";
|
||||
options.mySystem.de.gnome.systrayicons = mkEnableOption "Enable systray icons" // { default = true; };
|
||||
options.mySystem.de.gnome.gsconnect = mkEnableOption "Enable gsconnect (KDEConnect for GNOME)" // { default = true; };
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
# Ref: https://nixos.wiki/wiki/GNOME
|
||||
|
||||
# GNOME plz
|
||||
services = {
|
||||
displayManager = {
|
||||
defaultSession = "gnome";
|
||||
autoLogin = {
|
||||
enable = false;
|
||||
user = "jahanson"; # TODO move to config overlay
|
||||
};
|
||||
};
|
||||
|
||||
xserver = {
|
||||
enable = true;
|
||||
xkb.layout = "us"; # `localctl` will give you
|
||||
|
||||
displayManager = {
|
||||
gdm.enable = true;
|
||||
};
|
||||
desktopManager = {
|
||||
# GNOME
|
||||
gnome.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
udev.packages = optionals cfg.systrayicons [ pkgs.gnome.gnome-settings-daemon ]; # support appindicator
|
||||
};
|
||||
|
||||
# systyray icons
|
||||
# extra pkgs and extensions
|
||||
environment = {
|
||||
systemPackages = with pkgs; [
|
||||
wl-clipboard # ls ~/Downloads | wl-copy or wl-paste > clipboard.txt
|
||||
playerctl # gsconnect play/pause command
|
||||
pamixer # gcsconnect volume control
|
||||
gnome.gnome-tweaks
|
||||
gnome.dconf-editor
|
||||
|
||||
# This installs the extension packages, but
|
||||
# dont forget to enable them per-user in dconf settings -> "org/gnome/shell"
|
||||
gnomeExtensions.vitals
|
||||
gnomeExtensions.caffeine
|
||||
gnomeExtensions.dash-to-dock
|
||||
]
|
||||
++ optionals cfg.systrayicons [ pkgs.gnomeExtensions.appindicator ];
|
||||
};
|
||||
|
||||
# enable gsconnect
|
||||
# this method also opens the firewall ports required when enable = true
|
||||
programs.kdeconnect = mkIf
|
||||
cfg.gsconnect
|
||||
{
|
||||
enable = true;
|
||||
package = pkgs.gnomeExtensions.gsconnect;
|
||||
};
|
||||
|
||||
# GNOME connection to browsers - requires flag on browser as well
|
||||
services.gnome.gnome-browser-connector.enable = lib.any
|
||||
(user: user.programs.firefox.enable)
|
||||
(lib.attrValues config.home-manager.users);
|
||||
|
||||
# And dconf
|
||||
programs.dconf.enable = true;
|
||||
|
||||
# Exclude default GNOME packages that dont interest me.
|
||||
environment.gnome.excludePackages =
|
||||
(with pkgs; [
|
||||
gnome-photos
|
||||
gnome-tour
|
||||
gedit # text editor
|
||||
])
|
||||
++ (with pkgs.gnome; [
|
||||
cheese # webcam tool
|
||||
gnome-music
|
||||
gnome-terminal
|
||||
epiphany # web browser
|
||||
geary # email reader
|
||||
evince # document viewer
|
||||
gnome-characters
|
||||
totem # video player
|
||||
tali # poker game
|
||||
iagno # go game
|
||||
hitori # sudoku game
|
||||
atomix # puzzle game
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
}
|
62
nixos/modules/nixos/default.nix
Normal file
62
nixos/modules/nixos/default.nix
Normal file
|
@ -0,0 +1,62 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
{
|
||||
imports = [
|
||||
./system
|
||||
./programs
|
||||
./services
|
||||
./de
|
||||
./hardware
|
||||
./containers
|
||||
./lib.nix
|
||||
./security
|
||||
];
|
||||
|
||||
options.mySystem.persistentFolder = mkOption {
|
||||
type = types.str;
|
||||
description = "persistent folder for nixos mutable files";
|
||||
default = "/persist";
|
||||
};
|
||||
|
||||
options.mySystem.nasFolder = mkOption {
|
||||
type = types.str;
|
||||
description = "folder where nas mounts reside";
|
||||
default = "/mnt/nas";
|
||||
};
|
||||
|
||||
options.mySystem.nasAddress = mkOption {
|
||||
type = types.str;
|
||||
description = "NAS Address or name for the backup nas";
|
||||
default = "10.1.1.13";
|
||||
};
|
||||
|
||||
options.mySystem.domain = mkOption {
|
||||
type = types.str;
|
||||
description = "domain for hosted services";
|
||||
default = "";
|
||||
};
|
||||
|
||||
options.mySystem.internalDomain = mkOption {
|
||||
type = types.str;
|
||||
description = "domain for local devices";
|
||||
default = "";
|
||||
};
|
||||
|
||||
options.mySystem.purpose = mkOption {
|
||||
type = types.str;
|
||||
description = "System purpose";
|
||||
default = "Production";
|
||||
};
|
||||
|
||||
options.mySystem.monitoring.prometheus.scrapeConfigs = mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
description = "Prometheus scrape targets";
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
config = {
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${config.mySystem.persistentFolder} 777 - - -" #The - disables automatic cleanup, so the file wont be removed after a period
|
||||
];
|
||||
};
|
||||
}
|
5
nixos/modules/nixos/hardware/default.nix
Normal file
5
nixos/modules/nixos/hardware/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./nvidia
|
||||
];
|
||||
}
|
79
nixos/modules/nixos/hardware/nvidia/default.nix
Normal file
79
nixos/modules/nixos/hardware/nvidia/default.nix
Normal file
|
@ -0,0 +1,79 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.hardware.nvidia;
|
||||
in
|
||||
{
|
||||
options.mySystem.hardware.nvidia.enable = mkEnableOption "NVIDIA config";
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
# ref: https://nixos.wiki/wiki/Nvidia
|
||||
# Enable OpenGL
|
||||
hardware.opengl = {
|
||||
enable = true;
|
||||
driSupport = true;
|
||||
driSupport32Bit = true;
|
||||
};
|
||||
|
||||
hardware.opengl.extraPackages = with pkgs; [
|
||||
vaapiVdpau
|
||||
];
|
||||
|
||||
# This is for the benefit of VSCODE running natively in wayland
|
||||
environment.sessionVariables.NIXOS_OZONE_WL = "1";
|
||||
|
||||
hardware.nvidia = {
|
||||
|
||||
# Modesetting is required.
|
||||
modesetting.enable = true;
|
||||
|
||||
# Nvidia power management. Experimental, and can cause sleep/suspend to fail.
|
||||
# Enable this if you have graphical corruption issues or application crashes after waking
|
||||
# up from sleep. This fixes it by saving the entire VRAM memory to /tmp/ instead
|
||||
# of just the bare essentials.
|
||||
powerManagement.enable = false;
|
||||
|
||||
# Fine-grained power management. Turns off GPU when not in use.
|
||||
# Experimental and only works on modern Nvidia GPUs (Turing or newer).
|
||||
powerManagement.finegrained = false;
|
||||
|
||||
# Use the NVidia open source kernel module (not to be confused with the
|
||||
# independent third-party "nouveau" open source driver).
|
||||
# Support is limited to the Turing and later architectures. Full list of
|
||||
# supported GPUs is at:
|
||||
# https://github.com/NVIDIA/open-gpu-kernel-modules#compatible-gpus
|
||||
# Only available from driver 515.43.04+
|
||||
# Currently alpha-quality/buggy, so false is currently the recommended setting.
|
||||
open = false;
|
||||
|
||||
# Enable the Nvidia settings menu,
|
||||
# accessible via `nvidia-settings`.
|
||||
nvidiaSettings = true;
|
||||
|
||||
# Optionally, you may need to select the appropriate driver version for your specific GPU.
|
||||
# package = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||
|
||||
# manual build nvidia driver, works around some wezterm issues
|
||||
# https://github.com/wez/wezterm/issues/2011
|
||||
package =
|
||||
# let
|
||||
# rcu_patch = pkgs.fetchpatch {
|
||||
# url = "https://github.com/gentoo/gentoo/raw/c64caf53/x11-drivers/nvidia-drivers/files/nvidia-drivers-470.223.02-gpl-pfn_valid.patch";
|
||||
# hash = "sha256-eZiQQp2S/asE7MfGvfe6dA/kdCvek9SYa/FFGp24dVg=";
|
||||
# };
|
||||
# in
|
||||
config.boot.kernelPackages.nvidiaPackages.mkDriver {
|
||||
version = "550.67";
|
||||
sha256_64bit = "sha256-mSAaCccc/w/QJh6w8Mva0oLrqB+cOSO1YMz1Se/32uI=";
|
||||
sha256_aarch64 = "sha256-+UuK0UniAsndN15VDb/xopjkdlc6ZGk5LIm/GNs5ivA=";
|
||||
openSha256 = "sha256-M/1qAQxTm61bznAtCoNQXICfThh3hLqfd0s1n1BFj2A=";
|
||||
settingsSha256 = "sha256-FUEwXpeUMH1DYH77/t76wF1UslkcW721x9BHasaRUaM=";
|
||||
persistencedSha256 = "sha256-ojHbmSAOYl3lOi2X6HOBlokTXhTCK6VNsH6+xfGQsyo=";
|
||||
# patches = [ rcu_patch ];
|
||||
};
|
||||
};
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
};
|
||||
}
|
83
nixos/modules/nixos/lib.nix
Normal file
83
nixos/modules/nixos/lib.nix
Normal file
|
@ -0,0 +1,83 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
{
|
||||
|
||||
# container builder
|
||||
lib.mySystem.mkContainer = options: (
|
||||
let
|
||||
# nix doesnt have an exhausive list of options for oci
|
||||
# so here i try to get a robust list of security options for containers
|
||||
# because everyone needs more tinfoild hat right? RIGHT?
|
||||
|
||||
containerExtraOptions = lib.optionals (lib.attrsets.attrByPath [ "caps" "privileged" ] false options) [ "--privileged" ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "caps" "readOnly" ] false options) [ "--read-only" ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "caps" "tmpfs" ] false options) [ (map (folders: "--tmpfs=${folders}") tmpfsFolders) ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "caps" "noNewPrivileges" ] false options) [ "--security-opt=no-new-privileges" ]
|
||||
++ lib.optionals (lib.attrsets.attrByPath [ "caps" "dropAll" ] false options) [ "--cap-drop=ALL" ];
|
||||
|
||||
in
|
||||
{
|
||||
${options.app} = {
|
||||
image = "${options.image}";
|
||||
user = "${options.user}:${options.group}";
|
||||
environment = {
|
||||
TZ = config.time.timeZone;
|
||||
} // lib.attrsets.attrByPath [ "env" ] { } options;
|
||||
environmentFiles = lib.attrsets.attrByPath [ "envFiles" ] [ ] options;
|
||||
volumes = [ "/etc/localtime:/etc/localtime:ro" ]
|
||||
++ lib.attrsets.attrByPath [ "volumes" ] [ ] options;
|
||||
ports = lib.attrsets.attrByPath [ "ports" ] [ ] options;
|
||||
extraOptions = containerExtraOptions;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
# build a restic restore set for both local and remote
|
||||
lib.mySystem.mkRestic = options: (
|
||||
let
|
||||
excludePath = if builtins.hasAttr "excludePath" options then options.excludePath else [ ];
|
||||
timerConfig = {
|
||||
OnCalendar = "02:05";
|
||||
Persistent = true;
|
||||
RandomizedDelaySec = "3h";
|
||||
};
|
||||
pruneOpts = [
|
||||
"--keep-daily 7"
|
||||
"--keep-weekly 5"
|
||||
"--keep-monthly 12"
|
||||
];
|
||||
initialize = true;
|
||||
backupPrepareCommand = ''
|
||||
# remove stale locks - this avoids some occasional annoyance
|
||||
#
|
||||
${pkgs.restic}/bin/restic unlock --remove-all || true
|
||||
'';
|
||||
in
|
||||
{
|
||||
# local backup
|
||||
"${options.app}-local" = {
|
||||
inherit pruneOpts timerConfig initialize backupPrepareCommand;
|
||||
# Move the path to the zfs snapshot path
|
||||
paths = map (x: "${config.mySystem.system.resticBackup.mountPath}/${x}") options.paths;
|
||||
passwordFile = config.sops.secrets."services/restic/password".path;
|
||||
exclude = excludePath;
|
||||
repository = "${config.mySystem.system.resticBackup.local.location}/${options.appFolder}";
|
||||
# inherit (options) user;
|
||||
};
|
||||
|
||||
# remote backup
|
||||
"${options.app}-remote" = {
|
||||
inherit pruneOpts timerConfig initialize backupPrepareCommand;
|
||||
# Move the path to the zfs snapshot path
|
||||
paths = map (x: "${config.mySystem.system.resticBackup.mountPath}/${x}") options.paths;
|
||||
environmentFile = config.sops.secrets."services/restic/env".path;
|
||||
passwordFile = config.sops.secrets."services/restic/password".path;
|
||||
repository = "${config.mySystem.system.resticBackup.remote.location}/${options.appFolder}";
|
||||
exclude = excludePath;
|
||||
# inherit (options) user;
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
}
|
5
nixos/modules/nixos/programs/default.nix
Normal file
5
nixos/modules/nixos/programs/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./shell
|
||||
];
|
||||
}
|
5
nixos/modules/nixos/programs/shell/default.nix
Normal file
5
nixos/modules/nixos/programs/shell/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./fish.nix
|
||||
];
|
||||
}
|
28
nixos/modules/nixos/programs/shell/fish.nix
Normal file
28
nixos/modules/nixos/programs/shell/fish.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.shell.fish;
|
||||
in
|
||||
{
|
||||
options.mySystem.shell.fish =
|
||||
{
|
||||
enable = mkEnableOption "Fish";
|
||||
enablePlugins = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "If we want to add fish plugins";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Install fish systemwide
|
||||
config.programs.fish = mkIf cfg.enable {
|
||||
enable = true;
|
||||
vendor = {
|
||||
completions.enable = true;
|
||||
config.enable = true;
|
||||
functions.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
36
nixos/modules/nixos/security/acme/default.nix
Normal file
36
nixos/modules/nixos/security/acme/default.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.security.acme;
|
||||
in
|
||||
{
|
||||
options.mySystem.security.acme.enable = mkEnableOption "acme";
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
sops.secrets = {
|
||||
"security/acme/env".sopsFile = ./secrets.sops.yaml;
|
||||
"security/acme/env".restartUnits = [ "lego.service" ];
|
||||
};
|
||||
|
||||
environment.persistence."${config.mySystem.system.impermanence.persistPath}" = lib.mkIf config.mySystem.system.impermanence.enable {
|
||||
directories = [ "/var/lib/acme" ];
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "admin@${config.networking.domain}";
|
||||
|
||||
certs.${config.networking.domain} = {
|
||||
extraDomainNames = [
|
||||
"${config.networking.domain}"
|
||||
"*.${config.networking.domain}"
|
||||
];
|
||||
dnsProvider = "cloudflare";
|
||||
dnsResolver = "1.1.1.1:53";
|
||||
credentialsFile = config.sops.secrets."security/acme/env".path;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
}
|
50
nixos/modules/nixos/security/acme/secrets.sops.yaml
Normal file
50
nixos/modules/nixos/security/acme/secrets.sops.yaml
Normal file
|
@ -0,0 +1,50 @@
|
|||
security:
|
||||
acme:
|
||||
env: ENC[AES256_GCM,data:/exabYG1GvSCxe+TBeECudCN6DQLVBrifa9509skrNRYBsbm1UJRK+WxO0xcrAQkcb1Lse4WE95ueQurSFaY81w=,iv:oD2zcXbO12TlOeH0xLYsaHWw4PVjMHtbVm1LAWp89oo=,tag:dwGBevRXV1B4n/5Sveq5cg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age18kj3xhlvgjeg2awwku3r8d95w360uysu0w5ejghnp4kh8qmtge5qwa2vjp
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGVEVHekhud2xUclpURFZB
|
||||
bzgrSkh2TWFibndHcTBpb3AySjRnUWliYzJBCmlROE83ZmJNbWpLaTExOUNwTmZw
|
||||
dElIUThUQVo3MjlobjVrdFMrZUJHM1EKLS0tIGVlcU16Vm12eERKN1o1Ym1yRnJB
|
||||
UkR2YUlLSnBWT0QrWTJuS0hRMnhBM2MKBaaD1gtd52RwKKPf7Yi7fhVEot6kIhAg
|
||||
oaS589WtWIiIiEs/Fde8QfOEJ4aydhuyfVFGxsJkb8a5QGkjKP4Faw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1z3vjvkead2h934n3w4m5m7tg4tj5qlzagsq6ly84h3tcu7x4ldsqd3s5fg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiSEwyT21iZHl2cEtKZTRG
|
||||
RGwwclFtTnNkK2c0U2U0U2NTWTkrckllbHhrCkprUTRxcFJnT3hTS3VuUjZXQUti
|
||||
MDNWZGMrSmFDL2svaTJDZlEwcFpEeEUKLS0tIEVBMDlxZmVEU0UreS9KZnNodWcy
|
||||
bUF2WVRySUd6NDJpbFRiYWszVlFYeGMK7Cl76mjrhdMNKy3SXQ4KqpUJl/P9peJc
|
||||
O+EZ0Q1m0tZrShg1soqdMb1p/00ubvy+Rvxx5Tq0jsIF/Lq0Y3Q3CA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1a8z3p24v32l9yxm5z2l8h7rpc3nhacyfv4jvetk2lenrvsdstd3sdu2kaf
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5U0cyRlFDaCsvSEZyeE1q
|
||||
WXpUdU5teVpGT1J6dkJ3VHJudG5UaEIvMlYwCm8xcldxOTFEV3JJbUhYbHNjZjgw
|
||||
T2tDZERTNnZtdVEvNWo5STZTdzZYbnMKLS0tIHpXQUREODAzOWIzcGVxZFJ1a2Rh
|
||||
S2U3T2NUdkVKL3VhWGtRTXUrclJ3TnMKE+6waO9P3EWCGeBRmh3OH689ttLU0F0G
|
||||
hEeBbwYSXfrXtHGSEwwNo++5vP1UVA7KUvLTF2G3mM2nhztJwacWtg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1d9p83j52m2xg0vh9k7q0uwlxwhs3y6tlv68yg9s2h9mdw2fmmsqshddz5m
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsSEREWEtSWTFUN1l3Uktp
|
||||
YlJCNUZEMnBJL0xQc21VenBkVTgrcVBDQlJFCm51QkhVK2J4ODNQN3AyZ2V4dnQw
|
||||
SVI2blo4SzdSYVdpeDluSFJ1YjFscXMKLS0tIEFMQXAyMGc2MHdMYjkxeHZOWHJ3
|
||||
TnJ6dFBkUGpXMTBjRU5MMVJGTWZmd2sKh83VVst9g3e9lbx2v3b46X23HHtQAeS/
|
||||
//oLEkBDuk5yqnNFtbcSGsWI9DBh9mD87bupw0Hz7GXTC/5LkApTkQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-05-18T16:39:41Z"
|
||||
mac: ENC[AES256_GCM,data:tiHQmGUiTuM6aH5Vf9abJUIPDlQ73vmXHCNvkoBHanX7k9ScDxpByqgnDaIR2Tue4SusVVgXFpAlSda9fTT/bSgLUA1+0Qxo4YDLRz5I0pp4sCXAGVELHguADKwAbv+AyT7x4idzecLZ532RGqKkLWHljfOzHtAAlA8FBHH3ylk=,iv:iHlFeshdBreirhJGCBYUucUkz0oEbxYLo6dIeab73e0=,tag:ZeUXSWla9hDldeoqFIw+/g==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
6
nixos/modules/nixos/security/default.nix
Normal file
6
nixos/modules/nixos/security/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./acme
|
||||
];
|
||||
}
|
22
nixos/modules/nixos/services/cockpit/default.nix
Normal file
22
nixos/modules/nixos/services/cockpit/default.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.cockpit;
|
||||
in
|
||||
{
|
||||
options.mySystem.services.cockpit.enable = mkEnableOption "Cockpit";
|
||||
|
||||
config.services.cockpit = mkIf cfg.enable {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
package = pkgs.cockpit.overrideAttrs (old: {
|
||||
# remove packagekit and selinux, don't work on NixOS
|
||||
postBuild = ''
|
||||
${old.postBuild}
|
||||
rm -rf \
|
||||
dist/packagekit \
|
||||
dist/selinux
|
||||
'';
|
||||
});
|
||||
};
|
||||
}
|
12
nixos/modules/nixos/services/default.nix
Normal file
12
nixos/modules/nixos/services/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
imports = [
|
||||
./cockpit
|
||||
./forgejo
|
||||
./nginx
|
||||
./podman
|
||||
./postgresql
|
||||
./radicale
|
||||
./reboot-required-check.nix
|
||||
./restic
|
||||
];
|
||||
}
|
92
nixos/modules/nixos/services/forgejo/default.nix
Normal file
92
nixos/modules/nixos/services/forgejo/default.nix
Normal file
|
@ -0,0 +1,92 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.forgejo;
|
||||
http_port = 3000;
|
||||
serviceUser = "forgejo";
|
||||
domain = "git.hsn.dev";
|
||||
in
|
||||
{
|
||||
options.mySystem.services.forgejo = {
|
||||
enable = mkEnableOption "Forgejo";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.nginx = {
|
||||
virtualHosts.${domain} = {
|
||||
forceSSL = true;
|
||||
useACMEHost = config.networking.domain;
|
||||
extraConfig = ''
|
||||
client_max_body_size 512M;
|
||||
'';
|
||||
locations."/".proxyPass = "http://127.0.0.1:${toString http_port}";
|
||||
};
|
||||
};
|
||||
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
# enable sql db dumps daily
|
||||
dump.enable = true;
|
||||
database.type = "postgres";
|
||||
# Enable support for Git Large File Storage
|
||||
lfs.enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = domain;
|
||||
# You need to specify this to remove the port from URLs in the web UI.
|
||||
ROOT_URL = "https://${domain}/";
|
||||
HTTP_PORT = http_port;
|
||||
# Default landing page on 'explore'
|
||||
LANDING_PAGE = "explore";
|
||||
};
|
||||
# You can temporarily allow registration to create an admin user.
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
ENABLE_NOTIFY_MAIL = true;
|
||||
REGISTER_EMAIL_CONFIRM = true;
|
||||
REQUIRE_SIGNIN_VIEW = false;
|
||||
};
|
||||
indexer = {
|
||||
REPO_INDEXER_ENABLED = true;
|
||||
REPO_INDEXER_PATH = "indexers/repos.bleve";
|
||||
MAX_FILE_SIZE = 1048576;
|
||||
REPO_INDEXER_INCLUDE = "";
|
||||
REPO_INDEXER_EXCLUDE = "resources/bin/**";
|
||||
};
|
||||
picture = {
|
||||
AVATAR_UPLOAD_PATH = "/var/lib/forgejo/data/avatars";
|
||||
REPOSITORY_AVATAR_UPLOAD_PATH = "/var/lib/forgejo/data/repo-avatars";
|
||||
};
|
||||
# Add support for actions, based on act: https://github.com/nektos/act
|
||||
actions = {
|
||||
ENABLED = true;
|
||||
};
|
||||
# Sending emails is completely optional
|
||||
# You can send a test email from the web UI at:
|
||||
# Profile Picture > Site Administration > Configuration > Mailer Configuration
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
SMTP_ADDR = "smtp.mailgun.org";
|
||||
FROM = "git@hsn.dev";
|
||||
USER = "git@mg.hsn.dev";
|
||||
SMTP_PORT = 587;
|
||||
};
|
||||
session = {
|
||||
COOKIE_SECURE = true;
|
||||
COOKIE_NAME = "session";
|
||||
};
|
||||
};
|
||||
mailerPasswordFile = config.sops.secrets."services/forgejo/smtp/password".path;
|
||||
};
|
||||
# sops
|
||||
sops.secrets."services/forgejo/smtp/password" = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
owner = serviceUser;
|
||||
mode = "400";
|
||||
restartUnits = [ "forgejo.service" ];
|
||||
};
|
||||
environment.persistence."${config.mySystem.system.impermanence.persistPath}" = lib.mkIf config.mySystem.system.impermanence.enable {
|
||||
directories = [ "/var/lib/forgejo" ];
|
||||
};
|
||||
};
|
||||
}
|
51
nixos/modules/nixos/services/forgejo/secrets.sops.yaml
Normal file
51
nixos/modules/nixos/services/forgejo/secrets.sops.yaml
Normal file
|
@ -0,0 +1,51 @@
|
|||
services:
|
||||
forgejo:
|
||||
smtp:
|
||||
password: ENC[AES256_GCM,data:p5iDVW+V0aIlj9RTHpMgko/1ahVkiHXafgm2u2g3TTrYFORBqCJqv+lCSSm4mGIabn4=,iv:GIx/dnn1y6Is6uzKEkmo326AUSS+I5RnLsV2duKHPBo=,tag:7R4222rGEsK+egunnB+llg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age18kj3xhlvgjeg2awwku3r8d95w360uysu0w5ejghnp4kh8qmtge5qwa2vjp
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVOU9SMEZvQUxhZWU2dzJ0
|
||||
Z1ZUODd0R2Rtb2lmaHhweC9Tb0J2anJuRno4Cis5UGZHc3pobkQ2OUJwSy9tV1RF
|
||||
SmNvUi9Xek9oVFdPdzZQUnlJeWtBSEEKLS0tIFpoWTZOYlFOK2p4bTFaUVhGV1hz
|
||||
dlpWOWhLT2VtYXdDQjJlWnh4T05TT3MKJtewm9QN1EfT8IQkkHdH0GGNDyg1wH6Z
|
||||
Ja6lcZB580FPEHwoMC7cayQe5v82vbQsj6s8mOaUW9yRQLMQMkmOfA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1z3vjvkead2h934n3w4m5m7tg4tj5qlzagsq6ly84h3tcu7x4ldsqd3s5fg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6bUNpMWJ1YklkV1JPMnFi
|
||||
S0tiajlKblV5aTU2djJaQjN0M1IwOU9pdTNRCnFycmQ5WHFadmxhZ1R6a1ZHYjlW
|
||||
TjVCN2dUelc5Qkt5Y0ZtYUtNRHN0WTAKLS0tIDFKSUE2YzFmQzB1TjgrRDFEalJO
|
||||
MDg0bU9NS3VObVVYNDAvY1JIRU5xZEEKSWzp9smLNYypodRIh49XPBxS536XtFWf
|
||||
kJWaLiUfULifcN46F8Tyts9dGHXx/bOgM5rCFAqtqTL7EaJbam13pw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1a8z3p24v32l9yxm5z2l8h7rpc3nhacyfv4jvetk2lenrvsdstd3sdu2kaf
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuQ09PSWwyY2tGZzdyOGxq
|
||||
KzZuUW95Z2QzVXY4dk5tRGZ3MXMxNW9INXlRCmkra2t2UUMwWnBhM0VoTnpUaWIx
|
||||
UW13a3VxZWJyL0ZDdk1IVXJNQitpblkKLS0tIGMwZHJqOGt4Y2FCUUUrc2tEQjY0
|
||||
eWp3WmdOMUlTNVlUT3FMM0JCTnViQ28KE6rpeFodW4BAIDVdjpgPpRs26XgUya3b
|
||||
Xbg6IuB90DvzNMKkoGB36Dh5cWUGFBsJ3QYopSDQGFbUepyDQa4Wvw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1d9p83j52m2xg0vh9k7q0uwlxwhs3y6tlv68yg9s2h9mdw2fmmsqshddz5m
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6VG9uejd2YTZ4c1p3akFZ
|
||||
dUtEbXk3S1UzeEhLeld4VXVLK1dVKytlOEc4ClFwbVVUUG9SbzB2bDZwRHA2cE4y
|
||||
STFLOWR3S0YrQ1FBbjJDV3o1aW1rNjgKLS0tIDlnQkZhRlpXanY5TzViVzdTNGpo
|
||||
NDhZZ24zWmwwNVE4VDM0bllyUkdxVncKdyYx4r4ERRy2lz7b2oK4JvzF1RnIJ/mV
|
||||
neTz0N1LSdmTUAOUtRT7D73tR6HhBZQNxH4LIsYiRllto46mEamx7g==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-05-18T16:39:41Z"
|
||||
mac: ENC[AES256_GCM,data:TQ019mze1TDfHM3unUvhLzQOdPVhZ0lIw+CbcuSGIqpjITr7nGVRYtPMvHtY9taxaAQgpdJghOaP9MS/YR6KT9II54qYtel944rmOHxOIpB8Oy/mRHBJvx1JhQxHzxPx6hLsLxNagSbgIpyiNGwMiR2gedBLPI/BBNcPGESiMTA=,iv:m4UnG4p0eWzRmspSU/RL4HSeq3Fr5t+9FnNMxgCMOJE=,tag:w2aJxYjVoEHlaQAT+VAa7g==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
62
nixos/modules/nixos/services/nginx/default.nix
Normal file
62
nixos/modules/nixos/services/nginx/default.nix
Normal file
|
@ -0,0 +1,62 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.nginx;
|
||||
in
|
||||
{
|
||||
options.mySystem.services.nginx.enable = mkEnableOption "nginx";
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedBrotliSettings = true;
|
||||
|
||||
proxyResolveWhileRunning = true; # needed to ensure nginx loads even if it cant resolve vhosts
|
||||
|
||||
statusPage = true;
|
||||
enableReload = true;
|
||||
|
||||
# Only allow PFS-enabled ciphers with AES256
|
||||
sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
|
||||
|
||||
appendHttpConfig = ''
|
||||
# Minimize information leaked to other domains
|
||||
add_header 'Referrer-Policy' 'origin-when-cross-origin';
|
||||
|
||||
# Disable embedding as a frame
|
||||
add_header X-Frame-Options DENY;
|
||||
|
||||
# Prevent injection of code in other mime types (XSS Attacks)
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
'';
|
||||
commonHttpConfig = ''
|
||||
add_header X-Clacks-Overhead "GNU Terry Pratchett";
|
||||
'';
|
||||
# provide default host with returning error
|
||||
# else nginx returns the first server
|
||||
# in the config file... >:S
|
||||
virtualHosts = {
|
||||
"_" = {
|
||||
default = true;
|
||||
rejectSSL = true;
|
||||
extraConfig = "return 444;";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ 80 443 ];
|
||||
allowedUDPPorts = [ 80 443 ];
|
||||
};
|
||||
|
||||
# required for using acme certs
|
||||
users.users.nginx.extraGroups = [ "acme" ];
|
||||
};
|
||||
}
|
51
nixos/modules/nixos/services/podman/default.nix
Normal file
51
nixos/modules/nixos/services/podman/default.nix
Normal file
|
@ -0,0 +1,51 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.podman;
|
||||
in
|
||||
{
|
||||
options.mySystem.services.podman.enable = mkEnableOption "Podman";
|
||||
|
||||
config = mkIf cfg.enable
|
||||
{
|
||||
virtualisation.podman = {
|
||||
enable = true;
|
||||
|
||||
dockerCompat = true;
|
||||
extraPackages = [ pkgs.zfs ];
|
||||
|
||||
# regular cleanup
|
||||
autoPrune.enable = true;
|
||||
autoPrune.dates = "weekly";
|
||||
|
||||
# and add dns
|
||||
defaultNetwork.settings = {
|
||||
dns_enabled = true;
|
||||
};
|
||||
};
|
||||
virtualisation.oci-containers = {
|
||||
backend = "podman";
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
podman-tui # status of containers in the terminal
|
||||
lazydocker
|
||||
];
|
||||
|
||||
programs.fish.shellAliases = {
|
||||
# lazydocker --> lazypodman
|
||||
lazypodman="sudo DOCKER_HOST=unix:///run/podman/podman.sock lazydocker";
|
||||
};
|
||||
|
||||
networking.firewall.interfaces.podman0.allowedUDPPorts = [ 53 ];
|
||||
|
||||
# extra user for containers
|
||||
users.users.kah = {
|
||||
uid = 568;
|
||||
group = "kah";
|
||||
};
|
||||
users.groups.kah = { };
|
||||
users.users.jahanson.extraGroups = [ "kah" ];
|
||||
};
|
||||
|
||||
}
|
71
nixos/modules/nixos/services/postgresql/default.nix
Normal file
71
nixos/modules/nixos/services/postgresql/default.nix
Normal file
|
@ -0,0 +1,71 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.${category}.${app};
|
||||
app = "postgresql";
|
||||
category = "services";
|
||||
in
|
||||
{
|
||||
options.mySystem.${category}.${app} =
|
||||
{
|
||||
enable = mkEnableOption "${app}";
|
||||
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||
prometheus = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "Enable prometheus scraping";
|
||||
default = true;
|
||||
|
||||
};
|
||||
backupLocation = mkOption
|
||||
{
|
||||
type = lib.types.string;
|
||||
description = "Location for sql backups to be stored.";
|
||||
default = "/persist/backup/postgresql";
|
||||
};
|
||||
backup = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "Enable backups";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
identMap = ''
|
||||
# ArbitraryMapName systemUser DBUser
|
||||
superuser_map root postgres
|
||||
superuser_map postgres postgres
|
||||
# Let other names login as themselves
|
||||
superuser_map /^(.*)$ \1
|
||||
'';
|
||||
|
||||
authentication = ''
|
||||
#type database DBuser auth-method optional_ident_map
|
||||
local sameuser all peer map=superuser_map
|
||||
'';
|
||||
|
||||
settings = {
|
||||
max_connections = 200;
|
||||
random_page_cost = 1.1;
|
||||
};
|
||||
};
|
||||
|
||||
# enable backups
|
||||
services.postgresqlBackup = mkIf cfg.backup {
|
||||
enable = lib.mkForce true;
|
||||
location = cfg.backupLocation;
|
||||
};
|
||||
|
||||
### firewall config
|
||||
|
||||
# networking.firewall = mkIf cfg.openFirewall {
|
||||
# allowedTCPPorts = [ port ];
|
||||
# allowedUDPPorts = [ port ];
|
||||
# };
|
||||
|
||||
};
|
||||
}
|
110
nixos/modules/nixos/services/radicale/default.nix
Normal file
110
nixos/modules/nixos/services/radicale/default.nix
Normal file
|
@ -0,0 +1,110 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.${category}.${app};
|
||||
app = "radicale";
|
||||
category = "services";
|
||||
user = app; #string
|
||||
group = app; #string
|
||||
port = 5232; #int
|
||||
appFolder = "/var/lib/${app}";
|
||||
url = "${app}.jahanson.tech";
|
||||
in
|
||||
{
|
||||
options.mySystem.${category}.${app} =
|
||||
{
|
||||
enable = mkEnableOption "${app}";
|
||||
addToHomepage = mkEnableOption "Add ${app} to homepage" // { default = true; };
|
||||
monitor = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "Enable gatus monitoring";
|
||||
default = true;
|
||||
};
|
||||
prometheus = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "Enable prometheus scraping";
|
||||
default = true;
|
||||
};
|
||||
backups = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "Enable local backups";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
## Secrets
|
||||
sops.secrets."${category}/${app}/htpasswd" = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
owner = user;
|
||||
inherit group;
|
||||
restartUnits = [ "${app}.service" ];
|
||||
};
|
||||
|
||||
users.users.jahanson.extraGroups = [ group ];
|
||||
|
||||
environment.persistence."${config.mySystem.system.impermanence.persistPath}" = lib.mkIf config.mySystem.system.impermanence.enable {
|
||||
hideMounts = true;
|
||||
directories = [ "/var/lib/radicale/" ];
|
||||
};
|
||||
|
||||
## service
|
||||
services.radicale = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server.hosts = [ "0.0.0.0:${builtins.toString port}" ];
|
||||
auth = {
|
||||
type = "htpasswd";
|
||||
htpasswd_filename = config.sops.secrets."${category}/${app}/htpasswd".path;
|
||||
htpasswd_encryption = "plain";
|
||||
realm = "Radicale - Password Required";
|
||||
};
|
||||
storage.filesystem_folder = "/var/lib/radicale/collections";
|
||||
};
|
||||
};
|
||||
|
||||
### gatus integration
|
||||
mySystem.services.gatus.monitors = mkIf cfg.monitor [
|
||||
{
|
||||
name = app;
|
||||
group = "${category}";
|
||||
url = "https://${url}";
|
||||
interval = "1m";
|
||||
conditions = [ "[CONNECTED] == true" "[STATUS] == 200" "[RESPONSE_TIME] < 50" ];
|
||||
}
|
||||
];
|
||||
|
||||
### Ingress
|
||||
services.nginx.virtualHosts.${host} = {
|
||||
useACMEHost = config.networking.domain;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||
};
|
||||
};
|
||||
|
||||
### firewall config
|
||||
|
||||
# networking.firewall = mkIf cfg.openFirewall {
|
||||
# allowedTCPPorts = [ port ];
|
||||
# allowedUDPPorts = [ port ];
|
||||
# };
|
||||
|
||||
### backups
|
||||
warnings = [
|
||||
(mkIf (!cfg.backups && config.mySystem.purpose != "Development")
|
||||
"WARNING: Backups for ${app} are disabled!")
|
||||
];
|
||||
|
||||
services.restic.backups = mkIf cfg.backups (config.lib.mySystem.mkRestic
|
||||
{
|
||||
inherit app user;
|
||||
paths = [ appFolder ];
|
||||
inherit appFolder;
|
||||
});
|
||||
};
|
||||
}
|
50
nixos/modules/nixos/services/radicale/secrets.sops.yaml
Normal file
50
nixos/modules/nixos/services/radicale/secrets.sops.yaml
Normal file
|
@ -0,0 +1,50 @@
|
|||
services:
|
||||
radicale:
|
||||
htpasswd: ENC[AES256_GCM,data:4y6QUrivlOpUVNAGDuPb9w==,iv:AS13cN3EKDEfRCc6USejkYG4SEFS4sPoYrfok8jsfYg=,tag:60ZhYvH/+SQhZKR6M9Zlfw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age18kj3xhlvgjeg2awwku3r8d95w360uysu0w5ejghnp4kh8qmtge5qwa2vjp
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLc011SkxreTJSZERMemlS
|
||||
clM0NnhPekF3bFZiUXUreDZEN3dkN3NmN0RNCmM3UEdlV3Azbk4yL2dpS3ZRQVpv
|
||||
OWRQZ2E0eGU5cVIxRUU1c3RxMnpucEUKLS0tIHhjVXhtZEdVb3lvRnpoVGdJbkNq
|
||||
WEM1bGRUOFVrOU5jbmhxSmpRK0F4WWsKoV2ABFGgcLb0qMmorOzNaAzPf6AbMfr0
|
||||
PUdIkaXLJrF3Qi3bts96KhlPLUA7llArSMrUBtkXeCit6xS+87Imuw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1z3vjvkead2h934n3w4m5m7tg4tj5qlzagsq6ly84h3tcu7x4ldsqd3s5fg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBka1htN2tsN2ZZMkpDdHph
|
||||
dk5EY1JkM0hONlRiaXFhdGVIT0xuVDA0b2tBCnlTVExGOHg5RFdiRzU0RWd3dEg3
|
||||
aXB2UkhQRUF6QnBRN0FnNjRqMWIwRkUKLS0tIHJxOWNmR09PRVFQK1E3Um1laHJj
|
||||
VmdPdHl0OGtGODBIZHVzelByaVVoRTAKWb7/Th4zdNFo+K+rwi+nHpbftxnnMOlt
|
||||
BV0hsMpFBaQZXw01n9uw71MZiJZAbZOMA9P+toMKL9UwWSx+isa3gA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1a8z3p24v32l9yxm5z2l8h7rpc3nhacyfv4jvetk2lenrvsdstd3sdu2kaf
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNVTdVN1VnN1JpWkJFWC95
|
||||
Qmc3dUNQdUtWSjRwWlVSVlJ2aGZ1MXIrMEFJCjNtck5vcGVhNnFQNXk2MjlHSC9P
|
||||
aDU3WHQwbWdtbTBMcWdCUFE4Ulg5RlkKLS0tIGFDYnpGNE1SY2cvaUk4cWtBVmN6
|
||||
VGRIaEpkUk1qN1RsakV2YkdCbGJhUGcK8l4O+ysy9MeOq5uqnzt9GdkkH53BPtFf
|
||||
rmONh4pxPogBB0IsvZBz2NUsKkixnucEK0+SrF2X5x0wveMl/2Nm3Q==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1d9p83j52m2xg0vh9k7q0uwlxwhs3y6tlv68yg9s2h9mdw2fmmsqshddz5m
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3d2FMMStGS2dSYVcxMHNM
|
||||
QXdPenBQMXJlWFJWcHp0U0h0SkNpWWlNdXgwClBTMk1TQXg4M3ZueVZha1dNN1gv
|
||||
cTNuS3hBblNPQjBCa3o3N2xyNG9EZWMKLS0tIEo5SVc1b04xZndSNXQ4T3BOTmtr
|
||||
M1NVZkphS2E1R2c3dWovcHlaTloxTkUKsDiyHq40XddMdcZ/2UmOUnPSu44SWTRZ
|
||||
ZcDiYbfU4R7Ysgqaxl2iqBun/GOPWf4yeAbcynwXsLMUGG+XnsRWVw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-05-18T16:39:41Z"
|
||||
mac: ENC[AES256_GCM,data:9HLkT8t+LOSeVCWbjMhXMi7XduJ0nw4nZz9/dYCeyMW0w0/NscYn2avSUSks/5j14xAt4/NFmuM+KxW6z2dEdXE7DsCo1nWh+WyaTpL1QUId5xSWc6abQaexaKeRu/3QJ1wLNFgotaCuut96iFFTmvDL+t266ozxst8N3iR7zhk=,iv:NQwgSFv6Ogybrs6BMYl9eLeu0kNIJpmHR0MJCYHbCxA=,tag:X3BkmlHDt3E3GFT1iDYJHg==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
45
nixos/modules/nixos/services/reboot-required-check.nix
Normal file
45
nixos/modules/nixos/services/reboot-required-check.nix
Normal file
|
@ -0,0 +1,45 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.rebootRequiredCheck;
|
||||
in
|
||||
{
|
||||
options.mySystem.services.rebootRequiredCheck.enable = mkEnableOption "Reboot required check";
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Enable timer
|
||||
systemd.timers."reboot-required-check" = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
# start at boot
|
||||
OnBootSec = "0m";
|
||||
# check every hour
|
||||
OnUnitActiveSec = "1h";
|
||||
Unit = "reboot-required-check.service";
|
||||
};
|
||||
};
|
||||
|
||||
# Below script will check if initrd, kernel, kernel-modules that were booted match the current system
|
||||
# i.e. if a nixos-rebuild switch has upgraded anything
|
||||
systemd.services."reboot-required-check" = {
|
||||
script = ''
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# compare current system with booted sysetm to determine if a reboot is required
|
||||
if [[ "$(readlink /run/booted-system/{initrd,kernel,kernel-modules})" == "$(readlink /run/current-system/{initrd,kernel,kernel-modules})" ]]; then
|
||||
# check if the '/var/run/reboot-required' file exists and if it does, remove it
|
||||
if [[ -f /var/run/reboot-required ]]; then
|
||||
rm /var/run/reboot-required || { echo "Failed to remove /var/run/reboot-required"; exit 1; }
|
||||
fi
|
||||
else
|
||||
echo "reboot required"
|
||||
touch /var/run/reboot-required || { echo "Failed to create /var/run/reboot-required"; exit 1; }
|
||||
fi
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
102
nixos/modules/nixos/services/restic/default.nix
Normal file
102
nixos/modules/nixos/services/restic/default.nix
Normal file
|
@ -0,0 +1,102 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.system.resticBackup;
|
||||
in
|
||||
{
|
||||
options.mySystem.system.resticBackup = {
|
||||
local = {
|
||||
enable = mkEnableOption "Local backups" // { default = true; };
|
||||
location = mkOption
|
||||
{
|
||||
type = types.str;
|
||||
description = "Location for local backups";
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
remote = {
|
||||
enable = mkEnableOption "Remote backups" // { default = true; };
|
||||
location = mkOption
|
||||
{
|
||||
type = types.str;
|
||||
description = "Location for remote backups";
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
mountPath = mkOption
|
||||
{
|
||||
type = types.str;
|
||||
description = "Location for snapshot mount";
|
||||
default = "/mnt/nightly_backup";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
|
||||
# Warn if backups are disable and machine isnt a dev box
|
||||
warnings = [
|
||||
(mkIf (!cfg.local.enable && config.mySystem.purpose != "Development") "WARNING: Local backups are disabled!")
|
||||
(mkIf (!cfg.remote.enable && config.mySystem.purpose != "Development") "WARNING: Remote backups are disabled!")
|
||||
];
|
||||
|
||||
sops.secrets = mkIf (cfg.local.enable || cfg.remote.enable) {
|
||||
"services/restic/password" = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
owner = "kah";
|
||||
group = "kah";
|
||||
};
|
||||
|
||||
"services/restic/env" = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
owner = "kah";
|
||||
group = "kah";
|
||||
};
|
||||
};
|
||||
|
||||
environment.persistence = mkIf (cfg.local.enable || cfg.remote.enable) {
|
||||
"${config.mySystem.system.impermanence.persistPath}" = {
|
||||
directories = [ "/var/lib/containers" ];
|
||||
};
|
||||
};
|
||||
|
||||
# useful commands:
|
||||
# view snapshots - zfs list -t snapshot
|
||||
|
||||
# below takes a snapshot of the zfs persist volume
|
||||
# ready for restic syncs
|
||||
# essentially its a nightly rotation of atomic state at 2am.
|
||||
|
||||
# this is the safest option, as if you run restic
|
||||
# on live services/databases/etc, you will have
|
||||
# a bad day when you try and restore
|
||||
# (backing up a in-use file can and will cause corruption)
|
||||
|
||||
# ref: https://cyounkins.medium.com/correct-backups-require-filesystem-snapshots-23062e2e7a15
|
||||
systemd = mkIf (cfg.local.enable || cfg.remote.enable) {
|
||||
|
||||
timers.restic_nightly_snapshot = {
|
||||
description = "Nightly ZFS snapshot timer";
|
||||
wantedBy = [ "timers.target" ];
|
||||
partOf = [ "restic_nightly_snapshot.service" ];
|
||||
timerConfig.OnCalendar = "2:00";
|
||||
timerConfig.Persistent = "true";
|
||||
};
|
||||
|
||||
# recreate snapshot and mount, ready for backup
|
||||
# I used mkdir -p over a nix tmpfile, as mkdir -p exits cleanly
|
||||
# if the folder already exists, and tmpfiles complain
|
||||
# if the folder exists and is already mounted.
|
||||
services.restic_nightly_snapshot = {
|
||||
description = "Nightly ZFS snapshot for Restic";
|
||||
path = with pkgs; [ zfs busybox ];
|
||||
serviceConfig.Type = "simple";
|
||||
script = ''
|
||||
mkdir -p /mnt/nightly_backup/ && \
|
||||
umount ${cfg.mountPath} || true && \
|
||||
zfs destroy rpool/safe/persist@restic_nightly_snap || true && \
|
||||
zfs snapshot rpool/safe/persist@restic_nightly_snap && \
|
||||
mount -t zfs rpool/safe/persist@restic_nightly_snap ${cfg.mountPath}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
52
nixos/modules/nixos/services/restic/secrets.sops.yaml
Normal file
52
nixos/modules/nixos/services/restic/secrets.sops.yaml
Normal file
|
@ -0,0 +1,52 @@
|
|||
services:
|
||||
restic:
|
||||
password: ENC[AES256_GCM,data:23E=,iv:qK5OxK70KSC6nxsiovOWLDG1+6Mdlf+DNibc/mm3uGA=,tag:GV3V+T/Y8dO/L7pv+OkHzg==,type:str]
|
||||
repository: ENC[AES256_GCM,data:Sbao4Q==,iv:M9asdh36DY4Ys3RHugTeduECunSkrcL9yjE0j+CaCTk=,tag:Nmy8LNJbwr7cOTQd1p/kqQ==,type:str]
|
||||
env: ENC[AES256_GCM,data:wNFPsVW6DwZF6Qyyztt0Jw==,iv:PrP6gq+IMTUSKWIKt8zV8o1wbR51vZuZ95Yjwt07ypU=,tag:bBO0tYVR4qrSTZxMoQKgZA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age18kj3xhlvgjeg2awwku3r8d95w360uysu0w5ejghnp4kh8qmtge5qwa2vjp
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaMzZ0Y0FRaUdzY0tMeEx5
|
||||
VUJxZkFRUlY3clI1ejVCT0xPNnN3NTh1OHhZCnh2YkxkemZ0ekwxT1NQKzIvTGlH
|
||||
ejZISVJqVmM2UE1iM0M1eGpDSTN6VGcKLS0tIHJxSEhobUxoYWNXeE1LbWV6N0t1
|
||||
dGluUjZCbjFMMktnMFhHSVRscUtUNFEKFAEjmLUA0/9iZLQ4EhpPgyYYYkzQCpUL
|
||||
bo83xqeLmxY7jU8HGF2YNyBe+I9LHpZvxDTiXzBDiK0Bry9b57hWgg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1z3vjvkead2h934n3w4m5m7tg4tj5qlzagsq6ly84h3tcu7x4ldsqd3s5fg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLS1diU0xaU0M0amJEajM3
|
||||
YkpDeUh2VlNGa3liTFZMOGZYUDRoRUNGeldzCk5kSTcrOXNsclJTUnRoMEZqT0s5
|
||||
WTVKcFh4WVlSY0JlYUp0QmF4dWhCWlEKLS0tIGhoeERZWmZCcHR5bEtRZW1JczFy
|
||||
bEl2Yy9mb1NnbUx6WFFHUGhjUXNqV2cK4M0cAXzjNzG09g2FHCZUw8NQkw6Qw3o9
|
||||
G3uFAkWw1Dny8PewS4tzOErAZlUQ0iKJDgUVqOrrBrfvctTFtBseAw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1a8z3p24v32l9yxm5z2l8h7rpc3nhacyfv4jvetk2lenrvsdstd3sdu2kaf
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3WE9jVFRMRC9iNFVaTnNw
|
||||
OEovY3hwYW5kWnlrSTRIbFU5enFJVXlFVTJjCkdueno5bXZFS0VPU2RWdk5PUTRj
|
||||
Tk53UGJVZXZ3MExER2txVlRsVDIvY1kKLS0tIFI3VlNyYzB1S1RLS2JEbW54MTdW
|
||||
aHpBN3ZqWENXc1cvZE5Xa2FiaHNlU0UKQ5/xk21o60JLZ6xNcB0cFHkoTXMN99LD
|
||||
okhdVhlpml06ODoMIsFq/PR3adjeWJRjB7C4/Bz/wzlEUmze3TQMew==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1d9p83j52m2xg0vh9k7q0uwlxwhs3y6tlv68yg9s2h9mdw2fmmsqshddz5m
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3L0h2T3crY2JpaGMreS8z
|
||||
YkJLOTMvbTRKUFNlWXgzZkpPUVJ5eDFON3pFCnBEeDg1YnpxNXZvdWtPbndRT1VZ
|
||||
ZUhPRFE3TGFYaGluSDRjbkFHdi81NVEKLS0tIFJYZ3NaSVd6a25qMmxZV1VUNk50
|
||||
Wmo2cHY4cUZFMkFlUmNKcmg2RjcrUncKmbMWBL8r6R777c3SvFmmRpRY2oRQsf+A
|
||||
Yqlv0wmrD6A1B61SDRDwkmFggnk0PquznZD/y0JctqRqmcstAscyNQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-05-18T16:39:41Z"
|
||||
mac: ENC[AES256_GCM,data:sMTQ25VnUOrMSN9Ro7GoovFWh9Y/4RmHXm/mRHNuOGpl2utXGGQhAGM0F2lpdQwJfd/cRneiDfEJ1GSV+yaSPfTm2KFVVM+Kzl7AyHQO6W1dEvaMhJgGvxixc0SkF9zuU0WXnNOxW67fKUuuZZ69TwMdcVmwF1u7pV9tsONtgf8=,iv:Heynu00CnyU17zNkv1riz2hpulbXOeoi7ukj7c3Qk1g=,tag:Jqkaqq3XSXvENl/8a1z2QA==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
14
nixos/modules/nixos/system/default.nix
Normal file
14
nixos/modules/nixos/system/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
imports = [
|
||||
./impermanence.nix
|
||||
./motd
|
||||
./nix.nix
|
||||
./nfs
|
||||
./openssh.nix
|
||||
./pushover
|
||||
./security.nix
|
||||
./systempackages.nix
|
||||
./time.nix
|
||||
./zfs.nix
|
||||
];
|
||||
}
|
55
nixos/modules/nixos/system/impermanence.nix
Normal file
55
nixos/modules/nixos/system/impermanence.nix
Normal file
|
@ -0,0 +1,55 @@
|
|||
{ lib, config, ... }:
|
||||
let
|
||||
cfg = config.mySystem.system.impermanence;
|
||||
in
|
||||
with lib;
|
||||
{
|
||||
options.mySystem.system.impermanence = {
|
||||
enable = mkEnableOption "system impermanence";
|
||||
rootBlankSnapshotName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "blank";
|
||||
};
|
||||
rootPoolName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "rpool/local/root";
|
||||
};
|
||||
persistPath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/persist";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
# move ssh keys
|
||||
|
||||
# bind a initrd command to rollback to blank root after boot
|
||||
boot.initrd.postDeviceCommands = lib.mkAfter ''
|
||||
zfs rollback -r ${cfg.rootPoolName}@${cfg.rootBlankSnapshotName}
|
||||
'';
|
||||
|
||||
systemd.tmpfiles.rules = mkIf config.services.openssh.enable [
|
||||
"d /etc/ 0755 root root -" #The - disables automatic cleanup, so the file wont be removed after a period
|
||||
"d /etc/ssh/ 0755 root root -" #The - disables automatic cleanup, so the file wont be removed after a period
|
||||
];
|
||||
|
||||
environment.persistence."${cfg.persistPath}" = {
|
||||
hideMounts = true;
|
||||
directories =
|
||||
[
|
||||
"/var/log" # persist logs between reboots for debugging
|
||||
"/var/lib/cache" # cache files (restic, nginx, contaienrs)
|
||||
"/var/lib/nixos" # nixos state
|
||||
];
|
||||
files = [
|
||||
"/etc/machine-id"
|
||||
"/etc/adjtime" # hardware clock adjustment
|
||||
# ssh keys
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
"/etc/ssh/ssh_host_rsa_key"
|
||||
"/etc/ssh/ssh_host_rsa_key.pub"
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
}
|
98
nixos/modules/nixos/system/motd/default.nix
Normal file
98
nixos/modules/nixos/system/motd/default.nix
Normal file
|
@ -0,0 +1,98 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
motd = pkgs.writeShellScriptBin "motd"
|
||||
''
|
||||
#! /usr/bin/env bash
|
||||
source /etc/os-release
|
||||
service_status=$(systemctl list-units | grep podman-)
|
||||
RED="\e[31m"
|
||||
GREEN="\e[32m"
|
||||
BOLD="\e[1m"
|
||||
ENDCOLOR="\e[0m"
|
||||
LOAD1=`cat /proc/loadavg | awk {'print $1'}`
|
||||
LOAD5=`cat /proc/loadavg | awk {'print $2'}`
|
||||
LOAD15=`cat /proc/loadavg | awk {'print $3'}`
|
||||
|
||||
MEMORY=`free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)\n", $3,$2,$3*100 / $2 }'`
|
||||
|
||||
# time of day
|
||||
HOUR=$(date +"%H")
|
||||
if [ $HOUR -lt 12 -a $HOUR -ge 0 ]
|
||||
then TIME="morning"
|
||||
elif [ $HOUR -lt 17 -a $HOUR -ge 12 ]
|
||||
then TIME="afternoon"
|
||||
else
|
||||
TIME="evening"
|
||||
fi
|
||||
|
||||
|
||||
uptime=`cat /proc/uptime | cut -f1 -d.`
|
||||
upDays=$((uptime/60/60/24))
|
||||
upHours=$((uptime/60/60%24))
|
||||
upMins=$((uptime/60%60))
|
||||
upSecs=$((uptime%60))
|
||||
|
||||
figlet "$(hostname)" | lolcat -f
|
||||
printf "$BOLD %-20s$ENDCOLOR %s\n" "Role:" "${config.mySystem.purpose}"
|
||||
printf "\n"
|
||||
${lib.strings.concatStrings (lib.lists.forEach cfg.networkInterfaces (x: "printf \"$BOLD * %-20s$ENDCOLOR %s\\n\" \"IPv4 ${x}\" \"$(ip -4 addr show ${x} | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')\"\n"))}
|
||||
printf "$BOLD * %-20s$ENDCOLOR %s\n" "Release" "$PRETTY_NAME"
|
||||
printf "$BOLD * %-20s$ENDCOLOR %s\n" "Kernel" "$(uname -rs)"
|
||||
[ -f /var/run/reboot-required ] && printf "$RED * %-20s$ENDCOLOR %s\n" "A reboot is required"
|
||||
printf "\n"
|
||||
printf "$BOLD * %-20s$ENDCOLOR %s\n" "CPU usage" "$LOAD1, $LOAD5, $LOAD15 (1, 5, 15 min)"
|
||||
printf "$BOLD * %-20s$ENDCOLOR %s\n" "Memory" "$MEMORY"
|
||||
printf "$BOLD * %-20s$ENDCOLOR %s\n" "System uptime" "$upDays days $upHours hours $upMins minutes $upSecs seconds"
|
||||
printf "\n"
|
||||
if ! type "$zpool" &> /dev/null; then
|
||||
printf "$BOLD Zpool status: $ENDCOLOR\n"
|
||||
zpool status -x | sed -e 's/^/ /'
|
||||
fi
|
||||
if ! type "$zpool" &> /dev/null; then
|
||||
printf "$BOLD Zpool usage: $ENDCOLOR\n"
|
||||
zpool list -Ho name,cap,size | awk '{ printf("%-10s%+3s used out of %+5s\n", $1, $2, $3); }' | sed -e 's/^/ /'
|
||||
fi
|
||||
printf "\n"
|
||||
|
||||
if [[ -n "$service_status" ]]; then
|
||||
printf "$BOLDService status$ENDCOLOR\n"
|
||||
while IFS= read -r line; do
|
||||
if [[ $line =~ ".scope" ]]; then
|
||||
continue
|
||||
fi
|
||||
if echo "$line" | grep -q 'failed'; then
|
||||
service_name=$(echo $line | awk '{print $2;}' | sed 's/podman-//g')
|
||||
printf "$RED• $ENDCOLOR%-50s $RED[failed]$ENDCOLOR\n" "$service_name"
|
||||
elif echo "$line" | grep -q 'running'; then
|
||||
service_name=$(echo $line | awk '{print $1;}' | sed 's/podman-//g')
|
||||
printf "$GREEN• $ENDCOLOR%-50s $GREEN[active]$ENDCOLOR\n" "$service_name"
|
||||
else
|
||||
echo "service status unknown"
|
||||
fi
|
||||
done <<< "$service_status"
|
||||
fi
|
||||
'';
|
||||
cfg = config.mySystem.system.motd;
|
||||
in
|
||||
{
|
||||
options.mySystem.system.motd = {
|
||||
enable = lib.mkEnableOption "MOTD";
|
||||
networkInterfaces = lib.mkOption {
|
||||
description = "Network interfaces to monitor";
|
||||
type = lib.types.listOf lib.types.str;
|
||||
# default = lib.mapAttrsToList (_: val: val.interface)
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [
|
||||
motd
|
||||
pkgs.lolcat
|
||||
pkgs.figlet
|
||||
];
|
||||
programs.fish.interactiveShellInit = lib.mkIf config.programs.fish.enable ''
|
||||
motd
|
||||
'';
|
||||
};
|
||||
}
|
24
nixos/modules/nixos/system/nfs/default.nix
Normal file
24
nixos/modules/nixos/system/nfs/default.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ lib
|
||||
, config
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
cfg = config.mySystem.services.nfs;
|
||||
in
|
||||
{
|
||||
options.mySystem.services.nfs = {
|
||||
enable = lib.mkEnableOption "nfs";
|
||||
exports = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.nfs.server.enable = true;
|
||||
services.nfs.server.exports = cfg.exports;
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
2049
|
||||
];
|
||||
};
|
||||
}
|
38
nixos/modules/nixos/system/nix.nix
Normal file
38
nixos/modules/nixos/system/nix.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.nix;
|
||||
in
|
||||
{
|
||||
options.mySystem.nix = {
|
||||
autoOptimiseStore = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "If we want to auto optimise store";
|
||||
default = true;
|
||||
};
|
||||
gc = {
|
||||
enable = mkEnableOption "automatic garbage collection" // {
|
||||
default = true;
|
||||
};
|
||||
persistent = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "Persistent timer for gc, runs at startup if timer missed";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config.nix = {
|
||||
optimise.automatic = cfg.autoOptimiseStore;
|
||||
# automatically garbage collect nix store
|
||||
gc = mkIf cfg.gc.enable {
|
||||
# garbage collection
|
||||
automatic = cfg.gc.enable;
|
||||
dates = "daily";
|
||||
options = "--delete-older-than 7d";
|
||||
inherit (cfg.gc) persistent;
|
||||
};
|
||||
};
|
||||
}
|
38
nixos/modules/nixos/system/openssh.nix
Normal file
38
nixos/modules/nixos/system/openssh.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.services.openssh;
|
||||
in
|
||||
{
|
||||
options.mySystem.services.openssh = {
|
||||
enable = mkEnableOption "openssh" // { default = true; };
|
||||
passwordAuthentication = mkOption
|
||||
{
|
||||
type = lib.types.bool;
|
||||
description = "If password can be accepted for ssh (commonly disable for security hardening)";
|
||||
default = false;
|
||||
};
|
||||
permitRootLogin = mkOption
|
||||
{
|
||||
type = types.enum [ "yes" "without-password" "prohibit-password" "forced-commands-only" "no" ];
|
||||
description = "If root can login via ssh (commonly disable for security hardening)";
|
||||
default = "prohibit-password";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
settings = {
|
||||
# Harden
|
||||
PasswordAuthentication = cfg.passwordAuthentication;
|
||||
PermitRootLogin = cfg.permitRootLogin;
|
||||
# Automatically remove stale sockets
|
||||
StreamLocalBindUnlink = "yes";
|
||||
# Allow forwarding ports to everywhere
|
||||
GatewayPorts = "clientspecified";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
54
nixos/modules/nixos/system/pushover/default.nix
Normal file
54
nixos/modules/nixos/system/pushover/default.nix
Normal file
|
@ -0,0 +1,54 @@
|
|||
{ lib
|
||||
, config
|
||||
, pkgs
|
||||
, ...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.system.systemd.pushover-alerts;
|
||||
in
|
||||
{
|
||||
options.mySystem.system.systemd.pushover-alerts.enable = mkEnableOption "Pushover alerts for systemd failures" // { default = true; };
|
||||
options.systemd.services = mkOption {
|
||||
type = with types; attrsOf (
|
||||
submodule {
|
||||
config.onFailure = [ "notify-pushover@%n.service" ];
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
config = {
|
||||
# Warn if backups are disable and machine isnt a dev box
|
||||
warnings = [
|
||||
(mkIf (!cfg.enable && config.mySystem.purpose != "Development") "WARNING: Pushover SystemD notifications are disabled!")
|
||||
];
|
||||
|
||||
systemd.services."notify-pushover@" = mkIf cfg.enable {
|
||||
enable = true;
|
||||
onFailure = lib.mkForce [ ]; # cant refer to itself on failure
|
||||
description = "Notify on failed unit %i";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
EnvironmentFile = config.sops.secrets."services/pushover/env".path;
|
||||
};
|
||||
|
||||
# Script calls pushover with some deets.
|
||||
# Here im using the systemd specifier %i passed into the script,
|
||||
# which I can reference with bash $1.
|
||||
scriptArgs = "%i %H";
|
||||
script = ''
|
||||
${pkgs.curl}/bin/curl --fail -s -o /dev/null \
|
||||
--form-string "token=$PUSHOVER_API_KEY" \
|
||||
--form-string "user=$PUSHOVER_USER_KEY" \
|
||||
--form-string "priority=1" \
|
||||
--form-string "html=1" \
|
||||
--form-string "timestamp=$(date +%s)" \
|
||||
--form-string "url=https://$2:9090/system/services#/$1" \
|
||||
--form-string "url_title=View in Cockpit" \
|
||||
--form-string "title=Unit failure: '$1' on $2" \
|
||||
--form-string "message=<b>$1</b> has failed on <b>$2</b><br><u>Journal tail:</u><br><br><i>$(journalctl -u $1 -n 10 -o cat)</i>" \
|
||||
https://api.pushover.net/1/messages.json 2&>1
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
45
nixos/modules/nixos/system/security.nix
Normal file
45
nixos/modules/nixos/system/security.nix
Normal file
|
@ -0,0 +1,45 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.security;
|
||||
in
|
||||
{
|
||||
options.mySystem.security = {
|
||||
sshAgentAuth.enable = lib.mkEnableOption "openssh";
|
||||
wheelNeedsSudoPassword = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = "If wheel group users need password for sudo";
|
||||
default = true;
|
||||
};
|
||||
increaseWheelLoginLimits = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = "If wheel group users receive increased login limits";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
{
|
||||
security = {
|
||||
sudo.wheelNeedsPassword = cfg.wheelNeedsSudoPassword;
|
||||
# Don't bother with the lecture or the need to keep state about who's been lectured
|
||||
sudo.extraConfig = "Defaults lecture=\"never\"";
|
||||
pam.sshAgentAuth.enable = cfg.sshAgentAuth.enable;
|
||||
# Increase open file limit for sudoers
|
||||
pam.loginLimits = mkIf cfg.increaseWheelLoginLimits [
|
||||
{
|
||||
domain = "@wheel";
|
||||
item = "nofile";
|
||||
type = "soft";
|
||||
value = "524288";
|
||||
}
|
||||
{
|
||||
domain = "@wheel";
|
||||
item = "nofile";
|
||||
type = "hard";
|
||||
value = "1048576";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
20
nixos/modules/nixos/system/systempackages.nix
Normal file
20
nixos/modules/nixos/system/systempackages.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.mySystem.system;
|
||||
in
|
||||
{
|
||||
options.mySystem.system = {
|
||||
packages = mkOption
|
||||
{
|
||||
type = with types; listOf package;
|
||||
description = "List of system level package installs";
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
# System packages deployed globally.
|
||||
# This is NixOS so lets keep this liiight?
|
||||
# Ideally i'd keep most of it to home-manager user only stuff
|
||||
# and keep server role as light as possible
|
||||
config.environment.systemPackages = cfg.packages;
|
||||
}
|
22
nixos/modules/nixos/system/time.nix
Normal file
22
nixos/modules/nixos/system/time.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{ lib, config, ... }:
|
||||
let
|
||||
cfg = config.mySystem.time;
|
||||
in
|
||||
{
|
||||
options.mySystem.time = {
|
||||
timeZone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Timezone of system";
|
||||
default = "America/Chicago";
|
||||
};
|
||||
hwClockLocalTime = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = "If hardware clock is set to local time (useful for windows dual boot)";
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
time.timeZone = cfg.timeZone;
|
||||
time.hardwareClockInLocalTime = cfg.hwClockLocalTime;
|
||||
};
|
||||
}
|
40
nixos/modules/nixos/system/zfs.nix
Normal file
40
nixos/modules/nixos/system/zfs.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
let
|
||||
cfg = config.mySystem.system.zfs;
|
||||
in
|
||||
with lib;
|
||||
{
|
||||
options.mySystem.system.zfs = {
|
||||
enable = lib.mkEnableOption "zfs";
|
||||
mountPoolsAtBoot = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
# setup boot
|
||||
boot = {
|
||||
supportedFilesystems = [
|
||||
"zfs"
|
||||
];
|
||||
zfs = {
|
||||
forceImportRoot = false; # if stuck on boot, modify grub options , force importing isnt secure
|
||||
extraPools = cfg.mountPoolsAtBoot;
|
||||
};
|
||||
};
|
||||
services.zfs = {
|
||||
autoScrub.enable = true;
|
||||
# Defaults to weekly and is a bit too regular for my NAS
|
||||
autoScrub.interval = "weekly";
|
||||
trim.enable = true;
|
||||
};
|
||||
# Pushover notifications
|
||||
environment.systemPackages = with pkgs; [
|
||||
busybox
|
||||
];
|
||||
services.zfs.zed.settings = {
|
||||
ZED_PUSHOVER_TOKEN = "$(${pkgs.busybox}/bin/cat ${config.sops.secrets.pushover-api-key.path})";
|
||||
ZED_PUSHOVER_USER = "$(${pkgs.busybox}/bin/cat ${config.sops.secrets.pushover-user-key.path})";
|
||||
};
|
||||
};
|
||||
}
|
18
nixos/profiles/README.md
Normal file
18
nixos/profiles/README.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
## Profiles
|
||||
|
||||
Here are the profiles that each host picks from to build up a system.
|
||||
|
||||
Pair a role with a device type and the correct software and settings will be enabled for that configuration.
|
||||
Where possible use the `mySystem` option list to configure defaults via these profiles, so they _can_ be overridden later.
|
||||
|
||||
## Global
|
||||
|
||||
Default global settings that will apply to every device. Things like locale, timezone, etc that wont change machine to machine
|
||||
|
||||
## Hardware
|
||||
|
||||
Hardware settings so I can apply per set of machines as standard- i.e. all Raspi4's may benefit from a specific set of additions/hardware overlays.
|
||||
|
||||
## Role
|
||||
|
||||
The roles the machine has. Machines may have multiple roles.
|
44
nixos/profiles/global.nix
Normal file
44
nixos/profiles/global.nix
Normal file
|
@ -0,0 +1,44 @@
|
|||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
# NOTE
|
||||
# Some 'global' areas have defaults set in their respective modules.
|
||||
# These will be applied when the modules are loaded
|
||||
# Not the global role.
|
||||
# Not sure at this point a good way to manage globals in one place
|
||||
# without mono-repo config.
|
||||
|
||||
imports =
|
||||
[
|
||||
(modulesPath + "/installer/scan/not-detected.nix") # Generated by nixos-config-generate
|
||||
./global
|
||||
];
|
||||
config = {
|
||||
boot.tmp.cleanOnBoot = true;
|
||||
mySystem = {
|
||||
# basics for all devices
|
||||
time.timeZone = "America/Chicago";
|
||||
security.increaseWheelLoginLimits = true;
|
||||
system.packages = [ pkgs.bat ];
|
||||
domain = "hsn.dev";
|
||||
shell.fish.enable = true;
|
||||
|
||||
# But wont enable plugins globally, leave them for workstations
|
||||
# TODO: Make per device option
|
||||
system.resticBackup.remote.location = "s3:https://x.r2.cloudflarestorage.com/nixos-restic";
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
curl
|
||||
wget
|
||||
dnsutils
|
||||
jq
|
||||
yq
|
||||
];
|
||||
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
networking.domain = config.mySystem.domain;
|
||||
};
|
||||
|
||||
}
|
8
nixos/profiles/global/default.nix
Normal file
8
nixos/profiles/global/default.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./nix.nix
|
||||
./sops.nix
|
||||
./system.nix
|
||||
./users.nix
|
||||
];
|
||||
}
|
47
nixos/profiles/global/nix.nix
Normal file
47
nixos/profiles/global/nix.nix
Normal file
|
@ -0,0 +1,47 @@
|
|||
{ lib, nixpkgs, ... }:
|
||||
{
|
||||
## Below is to align shell/system to flake's nixpkgs
|
||||
## ref: https://nixos-and-flakes.thiscute.world/best-practices/nix-path-and-flake-registry
|
||||
|
||||
# Make `nix repl '<nixpkgs>'` use the same nixpkgs as the one used by this flake.
|
||||
environment.etc."nix/inputs/nixpkgs".source = "${nixpkgs}";
|
||||
nix = {
|
||||
# make `nix run nixpkgs#nixpkgs` use the same nixpkgs as the one used by this flake.
|
||||
registry.nixpkgs.flake = nixpkgs;
|
||||
channel.enable = false; # remove nix-channel related tools & configs, we use flakes instead.
|
||||
|
||||
# but NIX_PATH is still used by many useful tools, so we set it to the same value as the one used by this flake.
|
||||
# https://github.com/NixOS/nix/issues/9574
|
||||
settings.nix-path = lib.mkForce "nixpkgs=/etc/nix/inputs/nixpkgs";
|
||||
|
||||
settings = {
|
||||
# Enable flakes
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
|
||||
# Substitutions
|
||||
substituters = [
|
||||
"https://hsndev.cachix.org"
|
||||
"https://nix-community.cachix.org"
|
||||
"https://numtide.cachix.org"
|
||||
];
|
||||
|
||||
trusted-public-keys = [
|
||||
"hsndev.cachix.org-1:vN1/XGBZtMLnTFYDmTLDrullgZHSUYY3Kqt+Yg/C+tE="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
"numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE="
|
||||
];
|
||||
|
||||
# Fallback quickly if substituters are not available.
|
||||
connect-timeout = 25;
|
||||
# Avoid copying unnecessary stuff over SSH
|
||||
builders-use-substitutes = true;
|
||||
trusted-users = [ "root" "@wheel" ];
|
||||
warn-dirty = false;
|
||||
# The default at 10 is rarely enough.
|
||||
log-lines = lib.mkDefault 25;
|
||||
};
|
||||
};
|
||||
}
|
53
nixos/profiles/global/secrets.sops.yaml
Normal file
53
nixos/profiles/global/secrets.sops.yaml
Normal file
|
@ -0,0 +1,53 @@
|
|||
services:
|
||||
pushover:
|
||||
env: ENC[AES256_GCM,data:Ug92K492ytxkRMHTw6fmYKgpkz47gBg9aLxqivo+t5GejJbIU1cOewo88/7ASmslceTAiY57NcBTM56eHw7U9+HEq1IjX6RukM/OxZ27R4aMkLCdf1c7DNJ5GOOvX2Zo,iv:uVXUIervTvgLnr60oeWeysB08TR/jy9AjNMWLW75teo=,tag:l2ZGGzMKcVTdnKx5q7XJiA==,type:str]
|
||||
pushover-user-key: ENC[AES256_GCM,data:EWMIbhjq6+CH958H661xlxcVNLSKWHgxVyjTCU50,iv:Ph6z7Tri64WoPnCbTtrCA2ziprID1VXg8rynx6j6OOg=,tag:MZvq0AE1gp9Ga/73s6MWOw==,type:str]
|
||||
pushover-api-key: ENC[AES256_GCM,data:1rnQ/dgls1iLtx3efKT37PyrZyArVbRe7BjmKYqZ,iv:pRvkTjRtpf5PhXG555OR+TVmgzwmJnF8+Pb2wfbTKWU=,tag:3DFYTgLxQFQIT4qTP9cQgQ==,type:str]
|
||||
jahanson-password: ENC[AES256_GCM,data:HPLOlKHCpQIhat5qKKg=,iv:AawKpXj+2ZfEXg/eO2On4qtqHsoxksdRxH6nr+/oTGE=,tag:4wWfOGXybP6B88iGdFMF9A==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age18kj3xhlvgjeg2awwku3r8d95w360uysu0w5ejghnp4kh8qmtge5qwa2vjp
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGSTUzM1RzZEFVZTJBdFAz
|
||||
UnlYSmllNUdWa3BEa1BWQnBtbXZ1YTBnR25RClVIdy9YTUFyZ2VOdHlyVnNxTS9W
|
||||
Smw5dDc2S053ZElsdHZpdTRQc2dCWGsKLS0tIGZXUzNMTFlxaVFWNE1GREphanBu
|
||||
Rkdyd2lXUE5ucUVYT1FOZVlJR0hORGcKC5k9U3D+rfp4yEOx88APxmobjvOnf9jn
|
||||
POshirAInB/FjEOCb6gwmX8Y/0KJK1A69vwrx3+C4S+8xWcTQwnHqA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1z3vjvkead2h934n3w4m5m7tg4tj5qlzagsq6ly84h3tcu7x4ldsqd3s5fg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMeCtkNnllZ3RHSjdVWHpq
|
||||
N0pXM3B3RVJ2QnNwVXpvN2Q3R09mSFU1QWtnCnRvYnR6eVZCaEJkMjMxeEFzRHZ2
|
||||
enVodXlHUVFGcEZpTnFHT1VkTGwzbFkKLS0tIFhCTzQ3Ny9TOVBTamZ5SHIzKzFZ
|
||||
L2NsSjFGWHR4ZDBQR0FFZUdCUXpPRmcKdC6gSCxkHvThXEhp94b3Gx/5Tz4E2B6C
|
||||
TcwMZVgCC2VkSMASj1Jg08AX+xmJ92gc2xl/v9hQ3MWJbR38KBkaBw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1a8z3p24v32l9yxm5z2l8h7rpc3nhacyfv4jvetk2lenrvsdstd3sdu2kaf
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvMk1XRjdHQUtYbnNrb1oy
|
||||
SnlwVjBEUTd3dFdlaWh6UGlFTzR1RmpKYjE4CmhSKzFBOFFJSmtnM3Zwc3pKUy9j
|
||||
SmJiNFhoVmd0ZzE0V2xDK0dzaGhZRGMKLS0tIHlqbWozZHV1R3JSclQ0ZWNRejlD
|
||||
b1Q4RjJSWm1uSjRVNWd1WjBld1hUbk0KOB+7u0eLMslPCBE745dk7P8kVgELGp6m
|
||||
glDmVIqsKmvutZ54AhCtI/pOuL5vlmnstRn8MCXcZgXbm3a80BSNFg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1d9p83j52m2xg0vh9k7q0uwlxwhs3y6tlv68yg9s2h9mdw2fmmsqshddz5m
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOcUFiQk5yMGJBUitabTB6
|
||||
UHFVRXFVVWFoREV2dXZXcVJ0cG11TlhCUEVVCnAxQkJUUkU1VUhSaWNLQStpcUJu
|
||||
ZzJBQjlUQXhuZk9PZXRJSktnQWFHZmcKLS0tIFI4TUNwREF5cXNXZEd1NUJ3MGFH
|
||||
OFVrMXovMDVZTU5obE42NXkwektRa0UKmd1VNqD43WmhwICUohG2DLsZ9wYsGujp
|
||||
IERwiWAiCppqOEULQeZti8ioPHJDs6tjpuAR+vZ1TD/uhdJP4xsfcA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-05-18T16:39:41Z"
|
||||
mac: ENC[AES256_GCM,data:EXz+9dIdcI21WlJ9r/lewrfx9MjynA1eS82MMnO0BBiE2KV6XcMvrxStMIerXY/0nr2XGoZii8amo072naaHBTCwCsaDlx0Ry3oMyZYZNFwTM2mqIK93CymIkhe/qhMyNxDTmKc3QFEiRtimLnUx8YW27leS1b4mNFHcauXYNHA=,iv:EEmK39VBNXnJayk6z4MfHHsfj7OuwXUeLZQ06q2y2cE=,tag:9PLLS5BbwB1wmA+UV/oIwA==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
14
nixos/profiles/global/sops.nix
Normal file
14
nixos/profiles/global/sops.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{ ... }:
|
||||
{
|
||||
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
||||
# Secret for machine-specific pushover
|
||||
sops.secrets."services/pushover/env" = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
};
|
||||
sops.secrets.pushover-user-key = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
};
|
||||
sops.secrets.pushover-api-key = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
};
|
||||
}
|
13
nixos/profiles/global/system.nix
Normal file
13
nixos/profiles/global/system.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{ lib, pkgs, ... }:
|
||||
{
|
||||
system = {
|
||||
# Enable printing changes on nix build etc with nvd
|
||||
activationScripts.report-changes = ''
|
||||
PATH=$PATH:${lib.makeBinPath [ pkgs.nvd pkgs.nix ]}
|
||||
nvd diff $(ls -dv /nix/var/nix/profiles/system-*-link | tail -2)
|
||||
'';
|
||||
|
||||
# Do not change unless you know what you are doing
|
||||
stateVersion = "24.11";
|
||||
};
|
||||
}
|
39
nixos/profiles/global/users.nix
Normal file
39
nixos/profiles/global/users.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{ pkgs, config, ... }:
|
||||
let
|
||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||
in
|
||||
{
|
||||
sops.secrets = {
|
||||
jahanson-password = {
|
||||
sopsFile = ./secrets.sops.yaml;
|
||||
neededForUsers = true;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.jahanson = {
|
||||
isNormalUser = true;
|
||||
shell = pkgs.fish;
|
||||
hashedPasswordFile = config.sops.secrets.jahanson-password.path;
|
||||
extraGroups =
|
||||
[
|
||||
"wheel"
|
||||
]
|
||||
++ ifTheyExist [
|
||||
"network"
|
||||
"samba-users"
|
||||
"docker"
|
||||
"podman"
|
||||
"audio" # pulseaudio
|
||||
"libvirtd"
|
||||
];
|
||||
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBsUe5YF5z8vGcEYtQX7AAiw2rJygGf2l7xxr8nZZa7w"
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH3VVFenoJfnu+IFUlD79uxl7L8SFoRup33J2HGny4WEdRgGR41s0MpFKDBmxXZHy4O9Nh8NMMnpy5VhUefnIKI="
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPHFQ3hDjjrKsecn3jmSWYlRXy4IJCrepgU1HaIV5VcmB3mUFmIZ/pCZnPmIG/Gbuqf1PP2FQDmHMX5t0hTYG9A="
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIETR70eQJiXaJuB+qpI1z+jFOPbEZoQNRcq4VXkojWfU"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIATyScd8ZRhV7uZmrQNSAbRTs9N/Dbx+Y8tGEDny30sA"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJyA/yMPPo+scxBaDFUk7WeEyMAMhXUro5vi4feOKsJT jahanson@durincore"
|
||||
];
|
||||
};
|
||||
}
|
27
nixos/profiles/hw-generic-x86.nix
Normal file
27
nixos/profiles/hw-generic-x86.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{ lib, pkgs, ... }:
|
||||
with lib;
|
||||
{
|
||||
mySystem.system.packages = with pkgs; [
|
||||
ntfs3g
|
||||
];
|
||||
|
||||
boot = {
|
||||
|
||||
initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
|
||||
kernelModules = [ ];
|
||||
extraModulePackages = [ ];
|
||||
|
||||
# for managing/mounting ntfs
|
||||
supportedFilesystems = [ "ntfs" ];
|
||||
|
||||
loader = {
|
||||
systemd-boot.enable = true;
|
||||
efi.canTouchEfiVariables = true;
|
||||
grub.memtest86.enable = true;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
|
||||
}
|
26
nixos/profiles/hw-hetzner-cax.nix
Normal file
26
nixos/profiles/hw-hetzner-cax.nix
Normal file
|
@ -0,0 +1,26 @@
|
|||
{ lib, ... }: {
|
||||
imports = [ ];
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
mySystem = {
|
||||
services.openssh.enable = true;
|
||||
security.wheelNeedsSudoPassword = false;
|
||||
|
||||
# Restic backups disabled.
|
||||
# TODO: configure storagebox for hetzner backups
|
||||
system.resticBackup =
|
||||
{
|
||||
local.enable = false;
|
||||
remote.enable = false;
|
||||
};
|
||||
};
|
||||
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
|
||||
}
|
30
nixos/profiles/hw-thinkpad-t470.nix
Normal file
30
nixos/profiles/hw-thinkpad-t470.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
{ config, lib, ... }:
|
||||
{
|
||||
boot = {
|
||||
# Use the systemd-boot EFI boot loader.
|
||||
loader = {
|
||||
systemd-boot = {
|
||||
enable = true;
|
||||
};
|
||||
efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
};
|
||||
# Kernel mods
|
||||
initrd = {
|
||||
availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" ];
|
||||
kernelModules = [ ];
|
||||
};
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
extraModulePackages = [ ];
|
||||
};
|
||||
|
||||
networking = {
|
||||
useDHCP = lib.mkDefault true;
|
||||
};
|
||||
# networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.wlp4s0.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
36
nixos/profiles/role-dev.nix
Normal file
36
nixos/profiles/role-dev.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{ config, lib, pkgs, imports, boot, self, inputs, ... }:
|
||||
# Role for dev stations
|
||||
# Could be a workstatio or a headless server.
|
||||
|
||||
with config;
|
||||
{
|
||||
# git & vim are in global
|
||||
environment.systemPackages = with pkgs; [
|
||||
jq
|
||||
yq
|
||||
btop
|
||||
dnsutils
|
||||
nix
|
||||
|
||||
# nix dev
|
||||
dnscontrol # for updating internal DNS servers with homelab services
|
||||
|
||||
# TODO Move
|
||||
nil
|
||||
nixpkgs-fmt
|
||||
statix
|
||||
# nvd
|
||||
gh
|
||||
|
||||
# bind # for dns utils like named-checkconf
|
||||
inputs.nix-inspect.packages.${pkgs.system}.default
|
||||
];
|
||||
|
||||
programs.direnv = {
|
||||
# TODO move to home-manager
|
||||
enable = true;
|
||||
nix-direnv.enable = true;
|
||||
};
|
||||
|
||||
|
||||
}
|
47
nixos/profiles/role-server.nix
Normal file
47
nixos/profiles/role-server.nix
Normal file
|
@ -0,0 +1,47 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
# Role for headless servers
|
||||
# covers raspi's, sbc, NUC etc, anything
|
||||
# that is headless and minimal for running services
|
||||
with lib;
|
||||
{
|
||||
config = {
|
||||
# Enable monitoring for remote scraiping
|
||||
mySystem.services.promMonitoring.enable = true;
|
||||
mySystem.services.rebootRequiredCheck.enable = true;
|
||||
mySystem.security.wheelNeedsSudoPassword = false;
|
||||
mySystem.services.cockpit.enable = true;
|
||||
mySystem.system.motd.enable = true;
|
||||
mySystem.services.gatus.monitors = [{
|
||||
name = config.networking.hostName;
|
||||
group = "servers";
|
||||
url = "icmp://${config.networking.hostName}";
|
||||
interval = "1m";
|
||||
conditions = [ "[CONNECTED] == true" ];
|
||||
}];
|
||||
|
||||
nix.settings = {
|
||||
# TODO factor out into mySystem
|
||||
# Avoid disk full issues
|
||||
max-free = lib.mkDefault (1000 * 1000 * 1000);
|
||||
min-free = lib.mkDefault (128 * 1000 * 1000);
|
||||
};
|
||||
|
||||
services.logrotate.enable = mkDefault true;
|
||||
environment = {
|
||||
noXlibs = mkDefault true;
|
||||
systemPackages = [ pkgs.lazygit ];
|
||||
};
|
||||
documentation = {
|
||||
enable = mkDefault false;
|
||||
doc.enable = mkDefault false;
|
||||
info.enable = mkDefault false;
|
||||
man.enable = mkDefault false;
|
||||
nixos.enable = mkDefault false;
|
||||
};
|
||||
|
||||
programs.command-not-found.enable = mkDefault false;
|
||||
sound.enable = false;
|
||||
hardware.pulseaudio.enable = false;
|
||||
services.udisks2.enable = mkDefault false;
|
||||
};
|
||||
}
|
75
nixos/profiles/role-workstation.nix
Normal file
75
nixos/profiles/role-workstation.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
# Role for workstations
|
||||
# Covers desktops/laptops, expected to have a GUI and do workloads
|
||||
# Will have home-manager installs
|
||||
|
||||
with config;
|
||||
{
|
||||
mySystem = {
|
||||
|
||||
de.gnome.enable = true;
|
||||
|
||||
# Lets see if fish everywhere is OK on the pi's
|
||||
# TODO decide if i drop to bash on pis?
|
||||
shell.fish.enable = true;
|
||||
|
||||
# TODO make nfs server configurable
|
||||
# nfs.nas = {
|
||||
# enable = true;
|
||||
# lazy = true;
|
||||
# };
|
||||
|
||||
system.resticBackup.local.enable = false;
|
||||
system.resticBackup.remote.enable = false;
|
||||
|
||||
};
|
||||
|
||||
boot = {
|
||||
binfmt.emulatedSystems = [ "aarch64-linux" ]; # Enabled for raspi4 compilation
|
||||
plymouth.enable = true; # hide console with splash screen
|
||||
};
|
||||
|
||||
nix.settings = {
|
||||
# TODO factor out into mySystem
|
||||
# Avoid disk full issues
|
||||
max-free = lib.mkDefault (1000 * 1000 * 1000);
|
||||
min-free = lib.mkDefault (128 * 1000 * 1000);
|
||||
};
|
||||
|
||||
# set xserver videodrivers if used
|
||||
services.xserver.enable = true;
|
||||
|
||||
services = {
|
||||
fwupd.enable = config.boot.loader.systemd-boot.enable; # fwupd does not work in BIOS mode
|
||||
thermald.enable = true;
|
||||
smartd.enable = true;
|
||||
|
||||
# required for yubikey
|
||||
udev.packages = [ pkgs.yubikey-personalization ];
|
||||
pcscd.enable = true;
|
||||
};
|
||||
|
||||
hardware = {
|
||||
enableAllFirmware = true;
|
||||
sensor.hddtemp = {
|
||||
enable = true;
|
||||
drives = [ "/dev/disk/by-id/*" ];
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Sensors etc
|
||||
lm_sensors
|
||||
cpufrequtils
|
||||
cpupower-gui
|
||||
vscode
|
||||
vivaldi
|
||||
termius
|
||||
];
|
||||
|
||||
i18n = {
|
||||
defaultLocale = lib.mkDefault "en_US.UTF-8";
|
||||
};
|
||||
|
||||
programs.mtr.enable = true;
|
||||
}
|
13
renovate.json
Normal file
13
renovate.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"nix": {
|
||||
"enabled": true
|
||||
},
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true,
|
||||
"extends": ["schedule:daily"]
|
||||
}
|
||||
}
|
30
shell.nix
Normal file
30
shell.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Shell for bootstrapping flake-enabled nix and home-manager
|
||||
{ pkgs ? let
|
||||
# If pkgs is not defined, instantiate nixpkgs from locked commit
|
||||
lock = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.nixpkgs.locked;
|
||||
nixpkgs = fetchTarball {
|
||||
url = "https://github.com/nixos/nixpkgs/archive/${lock.rev}.tar.gz";
|
||||
sha256 = lock.narHash;
|
||||
};
|
||||
system = builtins.currentSystem;
|
||||
overlays = [ ]; # Explicit blank overlay to avoid interference
|
||||
in
|
||||
import nixpkgs { inherit system overlays; }
|
||||
, ...
|
||||
}:
|
||||
pkgs.mkShell {
|
||||
# Enable experimental features without having to specify the argument
|
||||
NIX_CONFIG = "experimental-features = nix-command flakes";
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
nix
|
||||
home-manager
|
||||
git
|
||||
nil
|
||||
nixpkgs-fmt
|
||||
go-task
|
||||
sops
|
||||
pre-commit
|
||||
gitleaks
|
||||
];
|
||||
}
|
Loading…
Reference in a new issue