chore(deps): update renovate/renovate docker tag to v37.68.4 #218

Open
renovate wants to merge 1976 commits from renovate/renovate-renovate-37.x into main
188 changed files with 21764 additions and 4116 deletions

12
.editorconfig Normal file
View file

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

View file

@ -0,0 +1,22 @@
name: Lint
on: [push]
jobs:
lint:
runs-on: docker
env:
container:
image: ghcr.io/catthehacker/ubuntu:js-20.04
steps:
- uses: actions/checkout@v3
- uses: https://github.com/cachix/install-nix-action@v22
env:
with:
nix_path: nixpkgs=channel:nixos-unstable
- run: |
sed -i '/^access-tokens/ d' /etc/nix/nix.conf
nix profile install 'nixpkgs#deadnix' 'nixpkgs#statix' 'nixpkgs#yamllint'
statix check .
deadnix -f
yamllint .

View file

@ -0,0 +1,22 @@
name: Nix
# on: [push]
jobs:
lint:
runs-on: docker
env:
container:
image: ghcr.io/catthehacker/ubuntu:js-20.04
steps:
- uses: actions/checkout@v3
- name: Check Nix flake inputs
uses: https://github.com/DeterminateSystems/flake-checker-action@v5
- uses: https://github.com/cachix/install-nix-action@v22
env:
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Run `nix flake check`
run: |
sed -i '/^access-tokens/ d' /etc/nix/nix.conf
nix run '.#' -- -V

View file

@ -0,0 +1,37 @@
name: Plex Update
on:
push:
branches:
- main
- ci
schedule:
- cron: '0 0 * * *'
jobs:
update:
runs-on: docker
container:
image: ghcr.io/catthehacker/ubuntu:js-20.04
steps:
- uses: actions/checkout@v3
- uses: https://github.com/cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-unstable
- env:
VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
VAULT_TOKEN: ${{ secrets.VAULT_TOKEN }}
run: |
git config user.name "Forgejo Actions Bot"
git config user.email "<>"
# Run Update script
./nixos/pkgs/plex-pass/update.sh
git add ./nixos/pkgs/plex-pass/
# Push if changed
if git status ./nixos/pkgs/plex-pass/ | grep -q "to be committed"; then
git commit -m "Update Plex"
git push origin main
fi

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
result
.direnv
.gcroots

5
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"Lua.diagnostics.globals": [
"vim"
]
}

31
.vscode/snippets.code-snippets vendored Normal file
View file

@ -0,0 +1,31 @@
{
// Place your infrastructure workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Create Host": {
"scope": "nix",
"prefix": "new_host",
"body": [
"{",
" hostname = \"$1\";",
" ip = \"$2\";",
" mac = \"$3\";",
" nix = ${4|false,true|};",
"}",
"$0"
]
}
}

27
.yamllint.yaml Normal file
View file

@ -0,0 +1,27 @@
ignore: |
charts/
docs/
.private/
.terraform/
.vscode/
gotk-components.yaml
gotk-sync.yaml
extends: default
rules:
document-start:
level: warning
present: false
empty-lines:
max-end: 1
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

18
README.md Normal file
View file

@ -0,0 +1,18 @@
# 0x76's Infrastructure
This repository contains my fleet of VMs, Containers and Bare Metal machines.
## Directory Structure
`flake.nix` is a NixOS flake which is the entrypoint for my NixOS config, it also contains a 'DevShell' containing all the tools needed
to deploy the infrastructure, this can be accessed running `nix develop`.
* **flux**: Kubernetes manifests as managed by [Flux]
* **nixos**: Nix configurations for my NixOS LXCs and VMs, deployed using [colmena].
[Flux]: https://github.com/fluxcd/flux2
[colmena]: https://colmena.cli.rs/unstable/
## Inspired by the following repos
* <https://github.com/colemickens/nixcfg>
* <https://github.com/serokell/pegasus-infra>
* <https://git.asraphiel.dev/j00lz/strato-infra>
* <https://github.com/tadfisher/flake>

File diff suppressed because it is too large Load diff

1741
flake.lock generated Normal file

File diff suppressed because it is too large Load diff

165
flake.nix Normal file
View file

@ -0,0 +1,165 @@
{
description = "0x76's infrastructure";
# For minecraft use:
# * https://github.com/Infinidoge/nix-minecraft
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable-small";
nixpkgs_stable.url = "nixpkgs/nixos-23.05";
nur.url = "github:nix-community/NUR";
colmena.url = "github:zhaofengli/colmena";
vault-secrets.url = "github:serokell/vault-secrets";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
riff.url = "github:DeterminateSystems/riff";
webcord.url = "github:fufexan/webcord-flake";
comma.url = "github:nix-community/comma";
mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
mailserver.inputs.nixpkgs.follows = "nixpkgs";
nixvim.url = "github:pta2002/nixvim";
nixos-generators.url = "github:nix-community/nixos-generators";
nixos-generators.inputs.nixpkgs.follows = "nixpkgs";
nixos-hardware.url = "github:nixos/nixos-hardware";
lanzaboote = {
url = "github:nix-community/lanzaboote";
# Optional but recommended to limit the size of your system closure.
inputs.nixpkgs.follows = "nixpkgs";
};
vault-unseal.url = "git+https://git.0x76.dev/v/vault-unseal.git";
attic.url = "github:zhaofengli/attic";
};
outputs =
{ self
, nixpkgs
, nixpkgs_stable
, vault-secrets
, colmena
, nixos-generators
, nur
, attic
, ...
}@inputs:
let
inherit (nixpkgs) lib;
util = import ./nixos/util.nix inputs;
inherit (util) hosts flat_hosts nixHosts;
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
overlays = [ (import ./nixos/pkgs) vault-secrets.overlay nur.overlay ];
};
pkgs_stable = import nixpkgs_stable {
inherit system;
config.allowUnfree = true;
};
# Define args each module gets access to (access to hosts is useful for DNS/DHCP)
specialArgs = { inherit hosts flat_hosts inputs pkgs_stable; };
# Script to apply local colmena deployments
apply-local = pkgs.writeShellScriptBin "apply-local" ''
"${
colmena.packages.${system}.colmena
}"/bin/colmena apply-local --sudo $@
'';
fast-repl = pkgs.writeShellScriptBin "fast-repl" ''
source /etc/set-environment
nix repl --file "${./.}/repl.nix" $@
'';
in
{
# Make the nixosConfigurations for compat reasons (e.g. vault)
nixosConfigurations =
(import (inputs.colmena + "/src/nix/hive/eval.nix") {
rawFlake = self;
colmenaOptions =
import (inputs.colmena + "/src/nix/hive/options.nix");
colmenaModules =
import (inputs.colmena + "/src/nix/hive/modules.nix");
}).nodes;
# Make the colmena configuration
colmena = lib.foldr (el: acc: acc // util.mkColmenaHost el)
{
meta = {
inherit specialArgs;
nixpkgs = pkgs;
};
}
nixHosts;
packages.${system} = {
inherit apply-local;
default = colmena.packages.${system}.colmena;
proxmox-lxc = nixos-generators.nixosGenerate {
inherit system specialArgs;
format = "proxmox-lxc";
modules = util.base_imports
++ [ (import ./nixos/templates/proxmox-lxc.nix) ];
};
# Broken
# proxmox-vm = nixos-generators.nixosGenerate {
# inherit system pkgs specialArgs;
# format = "proxmox";
# modules = util.base_imports
# ++ [ (import ./nixos/templates/proxmox-vm.nix) ];
# };
};
# Use by running `nix develop`
devShells.${system}.default = pkgs.mkShell {
VAULT_ADDR = "http://vault.olympus:8200/";
buildInputs = with pkgs; [
attic.packages.${pkgs.system}.attic
apply-local
colmena.packages.${system}.colmena
cachix
deadnix
fluxcd
k9s
kubectl
kubectx
statix
terraform
nixfmt
nixpkgs-fmt
nixUnstable
nil
vault
yamllint
jq
(vault-push-approle-envs self { })
(vault-push-approles self { })
fast-repl
weave-gitops
];
};
};
}

1
flux/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
old_cluster

12
flux/README.md Normal file
View file

@ -0,0 +1,12 @@
# Kubernetes Cluster
This is my personal Kubernetes Cluster. [Flux] watches this git repo and reconciles and changes made to the cluster.
## Bootstrap
```sh
flux bootstrap git --url ssh://gitea@git.0x76.dev:42/v/infrastructure.git --branch=main --path=flux/olympus/base --ssh-key-algorithm=ed25519
```
## References
Heavily inspired by: [onedr0p's cluster](https://github.com/onedr0p/home-cluster)
[Flux]: https://github.com/fluxcd/flux2

View file

@ -0,0 +1,15 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: weave-gitops
namespace: flux-system
spec:
refreshInterval: "5m"
secretStoreRef:
name: vault
kind: ClusterSecretStore
target:
name: oidc-auth
dataFrom:
- extract:
key: flux-system/weave-gitops

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- rbac.yaml
- external-secret.yaml
- weave-gitops-dashboard.yaml

View file

@ -0,0 +1,76 @@
---
# Admin cluster role
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: weave-admin
rules:
# Flux Resources
- apiGroups: ["kustomize.toolkit.fluxcd.io"]
resources: ["kustomizations"]
verbs: ["get", "list", "patch"]
- apiGroups: ["helm.toolkit.fluxcd.io"]
resources: ["helmreleases"]
verbs: ["get", "list", "patch"]
- apiGroups: ["source.toolkit.fluxcd.io"]
resources:
[
"buckets",
"helmcharts",
"gitrepositories",
"helmrepositories",
"ocirepositories",
]
verbs: ["get", "list", "patch"]
- apiGroups: ["notification.toolkit.fluxcd.io"]
resources: ["providers", "alerts"]
verbs: ["get", "list"]
- apiGroups: ["infra.contrib.fluxcd.io"]
resources: ["terraforms"]
verbs: ["get", "list", "patch"]
# Resources managed via Flux
- apiGroups: [""]
resources:
[
"configmaps",
"secrets",
"pods",
"services",
"namespaces",
"persistentvolumes",
"persistentvolumeclaims",
]
verbs: ["get", "list"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets"]
verbs: ["get", "list"]
- apiGroups: ["batch"]
resources: ["jobs", "cronjobs"]
verbs: ["get", "list"]
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles", "clusterroles", "rolebindings", "clusterrolebindings"]
verbs: ["get", "list"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list"]
# Feedback
- apiGroups: [""]
resources: ["events"]
verbs: ["get", "watch", "list"]
---
# Bind the cluster admin role to admins
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: weave-admin
subjects:
- kind: User
name: "victor@xirion.net"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: weave-admin
apiGroup: rbac.authorization.k8s.io

View file

@ -0,0 +1,48 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
annotations:
metadata.weave.works/description: This is the source location for the Weave GitOps
Dashboard's helm chart.
labels:
app.kubernetes.io/component: ui
app.kubernetes.io/created-by: weave-gitops-cli
app.kubernetes.io/name: weave-gitops-dashboard
app.kubernetes.io/part-of: weave-gitops
name: ww-gitops
namespace: flux-system
spec:
interval: 1h0m0s
type: oci
url: oci://ghcr.io/weaveworks/charts
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
annotations:
metadata.weave.works/description: This is the Weave GitOps Dashboard. It provides
a simple way to get insights into your GitOps workloads.
name: ww-gitops
namespace: flux-system
spec:
chart:
spec:
chart: weave-gitops
sourceRef:
kind: HelmRepository
name: ww-gitops
interval: 1h0m0s
values:
ingress:
enabled: true
hosts:
- host: flux.0x76.dev
paths:
- path: /
pathType: ImplementationSpecific
adminUser:
create: true
passwordHash: $2a$10$uIY/YYe.CcRerpVvfk04muX86hLfXRH.K6jATZaVPqp.bnUIu/bsC
username: admin

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- flux-system
- services
- websites

View file

@ -1,5 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- gotk-components.yaml
- gotk-sync.yaml
- renovate

View file

@ -0,0 +1,57 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: renovate
namespace: services
data:
config.js: |-
module.exports = {
"binarySource": "install",
"repositories": ["v/infrastructure"],
"flux": {
"fileMatch": ["flux/.+\\.ya?ml$"]
},
"helm-values": {
"fileMatch": ["flux/.+\\.ya?ml$"]
},
"kubernetes": {
"fileMatch": ["flux/.+\\.ya?ml$"]
},
"hostRules": [
{
"hostType": "docker",
"matchHost": "ghcr.io",
"username": "NULLx76",
"password": process.env.GITHUB_COM_TOKEN
}
],
"packageRules": [
{
"automerge": true,
"automergeType": "branch",
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"matchPackageNames": [
"renovate/renovate"
],
"matchPackagePrefixes": [
"git.0x76.dev"
]
}
],
// ignore individual fluxcd images
"ignoreDeps": [
"ghcr.io/fluxcd/helm-controller",
"ghcr.io/fluxcd/image-automation-controller",
"ghcr.io/fluxcd/image-reflector-controller",
"ghcr.io/fluxcd/kustomize-controller",
"ghcr.io/fluxcd/notification-controller",
"ghcr.io/fluxcd/source-controller"
],
"regexManagers": [
{
"fileMatch": [".+\\.nix"],
"matchStrings": ["image\\s*=\\s*\"(?<depName>.*?):(?<currentValue>.*?)\"\\s*;\\s*"],
"datasourceTemplate": "docker"
}
]
};

View file

@ -0,0 +1,46 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: renovate
namespace: services
spec:
# Run every 8 hours
schedule: "0 */8 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
volumes:
- name: config-volume
configMap:
name: renovate
- name: work-volume
emptyDir: {}
containers:
- name: renovate
image: renovate/renovate:37.68.4
volumeMounts:
- name: config-volume
mountPath: /opt/renovate/
- name: work-volume
mountPath: /tmp/renovate/
env:
- name: LOG_LEVEL
value: debug
- name: RENOVATE_ENDPOINT
value: "https://git.0x76.dev/api/v1/"
- name: RENOVATE_PLATFORM
value: gitea
- name: RENOVATE_AUTODISCOVER
value: "false"
- name: RENOVATE_GIT_AUTHOR
value: "Renovate Bot <renovate@xirion.net>"
- name: RENOVATE_CONFIG_FILE
value: "/opt/renovate/config.js"
- name: RENOVATE_BASE_DIR
value: "/tmp/renovate"
envFrom:
- secretRef:
name: renovate
restartPolicy: Never

View file

@ -0,0 +1,21 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: renovate
namespace: services
spec:
refreshInterval: "5m"
secretStoreRef:
name: vault
kind: ClusterSecretStore
target:
name: renovate
data:
- secretKey: RENOVATE_TOKEN
remoteRef:
key: gitops/renovate
property: gitea_token
- secretKey: GITHUB_COM_TOKEN
remoteRef:
key: gitops/renovate
property: github_token

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- external-secret.yaml
- config.yaml
- cronjob.yaml

View file

@ -0,0 +1,52 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: x76dev
namespace: websites
labels:
app: x76dev
spec:
replicas: 1
selector:
matchLabels:
app: x76dev
template:
metadata:
labels:
app: x76dev
spec:
containers:
- name: x76dev
image: git.0x76.dev/v/0x76.dev:5
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: x76dev
namespace: websites
spec:
selector:
app: x76dev
ports:
- protocol: TCP
port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: x76dev
namespace: websites
spec:
rules:
- host: "0x76.dev"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: x76dev
port:
number: 80

View file

@ -0,0 +1,52 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: blog
namespace: websites
labels:
app: blog
spec:
replicas: 1
selector:
matchLabels:
app: blog
template:
metadata:
labels:
app: blog
spec:
containers:
- name: blog
image: git.0x76.dev/v/blog.xirion.net:5
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: blog
namespace: websites
spec:
selector:
app: blog
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: blog
namespace: websites
spec:
rules:
- host: "blog.xirion.net"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: blog
port:
number: 8080

View file

@ -0,0 +1,52 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: internal
namespace: websites
labels:
app: internal
spec:
replicas: 1
selector:
matchLabels:
app: internal
template:
metadata:
labels:
app: internal
spec:
containers:
- name: internal
image: git.0x76.dev/v/internal.xirion.net:1
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: internal
namespace: websites
spec:
selector:
app: internal
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: internal
namespace: websites
spec:
rules:
- host: "internal.xirion.net"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: internal
port:
number: 8080

View file

@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
namespace: websites
resources:
- 0x76.yaml
- internal.yaml
- blog.yaml
- xirion.yaml

View file

@ -0,0 +1,52 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: xirion
namespace: websites
labels:
app: xirion
spec:
replicas: 1
selector:
matchLabels:
app: xirion
template:
metadata:
labels:
app: xirion
spec:
containers:
- name: xirion
image: git.0x76.dev/v/xirion.net:2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: xirion
namespace: websites
spec:
selector:
app: xirion
ports:
- protocol: TCP
port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: xirion
namespace: websites
spec:
rules:
- host: "xirion.net"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: xirion
port:
number: 80

View file

@ -0,0 +1,15 @@
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
interval: 10m0s
dependsOn:
- name: core
path: ./flux/olympus/apps
prune: true
sourceRef:
kind: GitRepository
name: flux-system

View file

@ -0,0 +1,13 @@
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: core
namespace: flux-system
spec:
interval: 10m0s
path: ./flux/olympus/core
prune: true
sourceRef:
kind: GitRepository
name: flux-system

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
# This manifest was generated by flux. DO NOT EDIT.
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: flux-system
@ -10,16 +11,16 @@ spec:
branch: main
secretRef:
name: flux-system
url: ssh://git@git.xirion.net:2222/olympus/flux.git
url: ssh://gitea@git.0x76.dev:42/v/infrastructure.git
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: flux-system
namespace: flux-system
spec:
interval: 10m0s
path: ./cluster
path: ./flux/olympus/base
prune: true
sourceRef:
kind: GitRepository

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- gotk-components.yaml
- gotk-sync.yaml
- repositories

View file

@ -0,0 +1,8 @@
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: external-secrets
namespace: flux-system
spec:
interval: 1h
url: https://charts.external-secrets.io

View file

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- external-secrets.yaml

View file

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helm

View file

@ -0,0 +1 @@
vault-secret-id.yaml

View file

@ -0,0 +1,29 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: external-secrets
namespace: security
spec:
interval: 30m
chart:
spec:
chart: external-secrets
version: 0.9.9
interval: 30m
sourceRef:
kind: HelmRepository
name: external-secrets
namespace: flux-system
values:
installCRDs: true
replicaCount: 1
leaderElect: true
# serviceMonitor:
# enabled: true
# webhook:
# serviceMonitor:
# enabled: true
# certController:
# serviceMonitor:
# enabled: true

View file

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helm-release.yaml
- vault-secret-store.yaml

View file

@ -0,0 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
name: vault-secret-id
namespace: security
data:
secret-id: XXXXXX # Obtain by `vault write -f auth/approle/role/external-secrets/secret-id`

View file

@ -0,0 +1,27 @@
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: vault
namespace: security
spec:
provider:
vault:
server: "http://vault.olympus:8200"
path: "k8s"
version: "v2"
auth:
# VaultAppRole authenticates with Vault using the
# App Role auth mechanism
# https://www.vaultproject.io/docs/auth/approle
appRole:
# Path where the App Role authentication backend is mounted
path: "approle"
# RoleID configured in the App Role authentication backend
# `vault read auth/approle/role/external-secrets/role-id`
roleId: "bb841a0e-45c1-9dab-36f0-f72647d6aff0"
# Reference to a key in a K8 Secret that contains the App Role SecretId
# (not commited in git)
secretRef:
name: "vault-secret-id"
namespace: "security"
key: "secret-id"

View file

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespaces
- external-secrets

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- websites.yaml
- security.yaml
- services.yaml

View file

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: security

View file

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: services

View file

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: websites

106
nixos/common/default.nix Normal file
View file

@ -0,0 +1,106 @@
{ lib, pkgs, inputs, config, ... }: {
imports =
[ ./users ./modules inputs.vault-secrets.nixosModules.vault-secrets ];
vault-secrets =
let
inherit (config.networking) domain hostName;
server = if domain == "olympus" then "vault" else "vault-0";
in
lib.mkIf (domain == "olympus" || domain == "hades") {
vaultPrefix = "${domain}_secrets/nixos";
vaultAddress = "http://${server}.${domain}:8200/";
approlePrefix = "${domain}-${hostName}";
};
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = { inherit inputs; };
sharedModules = [ ./hm-modules inputs.nixvim.homeManagerModules.nixvim ];
};
# Clean /tmp on boot.
boot.tmp.cleanOnBoot = true;
# Set your time zone.
time.timeZone = lib.mkDefault "Europe/Amsterdam";
# Systemd OOMd
# Fedora enables these options by default. See the 10-oomd-* files here:
# https://src.fedoraproject.org/rpms/systemd/tree/acb90c49c42276b06375a66c73673ac3510255
systemd.oomd = {
enableRootSlice = true;
enableUserServices = true;
};
# Nix Settings
nix = {
registry.nixpkgs.flake = inputs.nixpkgs;
nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
package = pkgs.nixUnstable;
settings = {
auto-optimise-store = true;
trusted-users = [ "root" "vivian" ];
substituters = [
"https://nix-community.cachix.org"
"https://nixpkgs-review-bot.cachix.org"
"https://colmena.cachix.org"
"https://cache.garnix.io"
"https://cachix.cachix.org"
];
trusted-public-keys = [
"cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"nixpkgs-review-bot.cachix.org-1:eppgiDjPk7Hkzzz7XlUesk3rcEHqNDozGOrcLc8IqwE="
"colmena.cachix.org-1:7BzpDnjjH8ki2CT3f6GdOk7QAzPOl+1t3LvTLXqYcSg="
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
];
};
optimise = {
automatic = true;
dates = [ "weekly" ];
};
gc = {
automatic = true;
dates = "weekly";
randomizedDelaySec = "3h";
options = "--delete-older-than 7d";
};
extraOptions = ''
experimental-features = nix-command flakes
'';
};
nixpkgs.config.allowUnfree = true;
nixpkgs.config.permittedInsecurePackages =
[ "nodejs-16.20.2" "nodejs-14.21.3" "openssl-1.1.1w" ];
# Limit the systemd journal to 100 MB of disk or the
# last 7 days of logs, whichever happens first.
services.journald.extraConfig = ''
SystemMaxUse=100M
MaxFileSec=7day
'';
# Enable SSH
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = lib.mkDefault false;
PermitRootLogin = lib.mkDefault "no";
};
};
# Debloat
documentation = {
enable = lib.mkForce false;
doc.enable = lib.mkForce false;
man.enable = lib.mkForce false;
info.enable = lib.mkForce false;
nixos.enable = lib.mkForce false;
};
system.disableInstallerTools = lib.mkDefault true;
}

View file

@ -0,0 +1,9 @@
# Common Desktop Config
This is where I store the NixOS config that is common between
my laptop and desktop
## Files
* `./default.nix`: Contains common systemwide configuration
* See also my NixOS [modules](../modules), specifically gnome
* `./home.nix`: Contains common user-level configuration
* See also my Home-Manager [modules](../hm-modules)

View file

@ -0,0 +1,114 @@
{ pkgs, lib, inputs, ... }: {
# Bootloader.
boot = {
kernelPackages = lib.mkDefault pkgs.linuxPackages_latest;
loader = {
systemd-boot.enable = lib.mkDefault true;
efi.canTouchEfiVariables = true;
efi.efiSysMountPoint = "/boot/efi";
};
kernel.sysctl = { "fs.inotify.max_user_watches" = 524288; };
initrd = {
systemd.enable = true;
verbose = false;
};
};
hardware.keyboard.qmk.enable = true;
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
users.vivian = import ./home.nix;
extraSpecialArgs = { inherit inputs; };
};
services = {
# Enable my config for the gnome desktop environment
v.gnome.enable = true;
# Enable CUPS to print documents.
printing.enable = true;
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
#jack.enable = true;
# use the example session manager (no others are packaged yet so this is enabled by default,
# no need to redefine it in your config for now)
#media-session.enable = true;
};
};
# Set your time zone.
time.timeZone = "Europe/Amsterdam";
# Select internationalisation properties.
i18n.defaultLocale = "en_GB.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "nl_NL.UTF-8";
LC_IDENTIFICATION = "nl_NL.UTF-8";
LC_MEASUREMENT = "nl_NL.UTF-8";
LC_MONETARY = "nl_NL.UTF-8";
LC_NAME = "nl_NL.UTF-8";
LC_NUMERIC = "nl_NL.UTF-8";
LC_PAPER = "nl_NL.UTF-8";
LC_TELEPHONE = "nl_NL.UTF-8";
LC_TIME = "nl_NL.UTF-8";
};
# Global Packages
environment.systemPackages = with pkgs; [ wireguard-tools sbctl podman-compose ];
# programs.virt-manager = {
# enable = true;
# };
# Enable sound with pipewire.
sound.enable = true;
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
virtualisation = {
podman.enable = true;
libvirtd = {
enable = true;
qemu.package = pkgs.qemu_kvm;
};
};
fonts.packages = with pkgs; [
material-design-icons
noto-fonts
noto-fonts-cjk
noto-fonts-emoji
dejavu_fonts
(nerdfonts.override {
fonts =
[ "DejaVuSansMono" "Ubuntu" "DroidSansMono" "NerdFontsSymbolsOnly" ];
})
];
programs = {
steam = {
enable = true;
# Open ports in the firewall for Steam Remote Play
remotePlay.openFirewall = true;
package = pkgs.steam.override {
extraPkgs = pkgs: with pkgs; [ gamescope mangohud ];
};
};
gamemode.enable = true;
adb.enable = true;
};
networking = {
# Networking
networkmanager.enable = true;
firewall.checkReversePath = false;
firewall.enable = false;
};
}

View file

@ -0,0 +1,95 @@
{ pkgs, inputs, config, ... }:
let
tex = pkgs.texlive.combine {
inherit (pkgs.texlive) scheme-full;
dnd-5e-latex-template = { pkgs = [ pkgs.v.dnd-5e-latex-template ]; };
};
my-python-packages = ps: with ps; [ pandas requests numpy ];
in {
home.packages = with pkgs; [
(python3.withPackages my-python-packages)
btop
calibre
celluloid
cinny-desktop
element-desktop-wayland
fusee-launcher
fractal-next
gcc
gimp
helix
inputs.attic.packages.${pkgs.system}.attic
inputs.comma.packages.${pkgs.system}.default
inputs.webcord.packages.${pkgs.system}.default
jetbrains.clion
jetbrains.rust-rover
kdenlive
libreoffice-fresh
mattermost-desktop
mullvad-vpn
neofetch
nixfmt
nixpkgs-review
plex-media-player
plexamp
spotify
qmk
solo2-cli
tex
unzip
yt-dlp
];
# Enable my own hm modules
themes.v.catppuccin.enable = true;
programs = {
v = {
vscode.enable = true;
nvim.enable = true;
rust.enable = true;
};
riff = {
enable = true;
direnv = true;
};
firefox.enable = true;
chromium = {
enable = true;
package = pkgs.ungoogled-chromium;
};
direnv = {
enable = true;
nix-direnv.enable = true;
};
zsh = {
enable = true;
sessionVariables = { DIRENV_LOG_FORMAT = ""; };
};
thunderbird = {
enable = true;
profiles.default = { isDefault = true; };
};
};
# Syncthing
services.syncthing.enable = true;
xdg.userDirs = let home = config.home.homeDirectory;
in {
enable = true;
createDirectories = true;
desktop = "${home}/.desktop";
documents = "${home}/cloud/Documents";
download = "${home}/dl";
music = "${home}/cloud/Music";
pictures = "${home}/cloud/Pictures";
publicShare = "${home}/.publicShare";
templates = "${home}/.templates";
videos = "${home}/cloud/Videos";
};
}

View file

@ -0,0 +1,13 @@
_: {
# See also: https://blog.xirion.net/posts/nixos-proxmox-lxc/
# Supress systemd services that don't work (correctly) on LXC
systemd.suppressedSystemUnits = [
"dev-mqueue.mount"
"sys-kernel-debug.mount"
"sys-fs-fuse-connections.mount"
];
# https://github.com/NixOS/nixpkgs/issues/157449#issuecomment-1459299764
boot.specialFileSystems."/run".options = [ "rshared" ];
}

View file

@ -0,0 +1,6 @@
_: {
networking.useDHCP = true;
# Enable qemu guest agent
services.qemuGuest.enable = true;
}

View file

@ -0,0 +1,40 @@
{ config, pkgs, lib, ... }:
with lib;
let cfg = config.themes.v.catppuccin;
in {
options.themes.v.catppuccin = { enable = mkEnableOption "catppuccin"; };
config =
let
theme = "Catppuccin-Pink-Dark";
cursorTheme = config.home.pointerCursor.name;
in
mkIf cfg.enable {
home.pointerCursor = {
name = "Bibata_Ghost";
size = 24;
package = pkgs.bibata-cursors-translucent;
};
gtk = {
enable = true;
theme = {
name = theme;
package = pkgs.catppuccin-gtk;
};
iconTheme = {
name = "Papirus-Dark";
package = pkgs.papirus-icon-theme.override { color = "violet"; };
};
cursorTheme = {
name = cursorTheme;
inherit (config.home.pointerCursor) package size;
};
};
programs.vscode = {
userSettings."workbench.colorTheme" = "Catppuccin Frappé";
extensions = [ pkgs.vscode-extensions.catppuccin.catppuccin-vsc ];
};
};
}

View file

@ -0,0 +1,3 @@
{ ... }: {
imports = [ ./catppuccin.nix ./nvim.nix ./riff.nix ./vscode.nix ./git.nix ./rust.nix ];
}

View file

@ -0,0 +1,31 @@
{ config, pkgs, lib, ... }:
with lib;
let cfg = config.programs.v.git;
in {
options.programs.v.git = { enable = mkEnableOption "git"; };
config = mkIf cfg.enable {
programs.git = {
enable = true;
package = pkgs.gitAndTools.gitFull;
userName = "0x76";
userEmail = "v@0x76.dev";
lfs.enable = true;
extraConfig = {
push.autoSetupRemote = true;
init.defaultBranch = "main";
# Git merge driver that always grabs upstream changes
# Useful for e.g. lock files
merge.ours = {
name = "Overwrite Upstream Changes";
driver = "cp -f '%A' '%B'";
};
};
difftastic.enable = true;
};
home.file.".config/git/attributes".text = ''
flake.lock merge=ours
'';
};
}

View file

@ -0,0 +1,158 @@
{ config, pkgs, lib, ... }:
with lib;
let cfg = config.programs.v.nvim;
in {
options.programs.v.nvim = { enable = mkEnableOption "nvim"; };
config = mkIf cfg.enable {
programs.nixvim = {
enable = true;
package = pkgs.neovim-unwrapped;
vimAlias = true;
globals.mapleader = " ";
options.number = true;
keymaps = [
{
mode = "n";
key = "<leader>ff";
action = "require('telescope.builtin').find_files";
lua = true;
}
{
mode = "n";
key = "<leader>fg";
action = "require('telescope.builtin').live_grep";
lua = true;
}
{
mode = "n";
key = "<C-_>";
action = "require('Comment.api').toggle.linewise.current";
lua = true;
}
{
mode = "n";
key = "g=";
action = "vim.lsp.buf.format";
lua = true;
}
];
# keymaps = [
# {
# key = "<leader>ff";
# mode = "n";
# lua = true;
# action = "require('telescope.builtin').find_files()";
# }
# {
# key = "<leader>fg";
# mode = "n";
# lua = true;
# action = "require('Comment.api').toggle.linewise.current()<cr>";
# }
# {
# key = "g=";
# mode = "n";
# lua = true;
# action = "vim.lsp.buf.format{async=true}<cr>";
# }
# ];
extraPlugins = with pkgs.vimPlugins; [ catppuccin-nvim luasnip ];
colorscheme = "catppuccin-frappe";
extraConfigLua = "";
plugins = {
bufferline.enable = true;
none-ls = {
enable = true;
sources = {
formatting.nixpkgs_fmt.enable = true;
code_actions.shellcheck.enable = true;
code_actions.statix.enable = true;
diagnostics = {
statix.enable = true;
deadnix.enable = true;
shellcheck.enable = true;
};
};
};
nix.enable = true;
treesitter = {
enable = true;
nixGrammars = true;
# ensureInstalled = [ ];
};
surround.enable = true;
fugitive.enable = true;
gitgutter.enable = true;
lualine = {
enable = true;
theme = "catppuccin";
};
telescope = {
enable = true;
extensions.fzf-native.enable = true;
extensions.fzf-native.fuzzy = true;
};
comment-nvim = { enable = true; };
lsp = {
enable = true;
servers = {
nil_ls.enable = true;
rust-analyzer.enable = true;
pyright.enable = true;
elixirls.enable = true;
clangd.enable = true;
yamlls.enable = true;
};
};
trouble.enable = true;
lspkind.enable = true;
nvim-cmp = {
enable = true;
autoEnableSources = true;
sources = [
{ name = "nvim_lsp"; }
{ name = "cmp-latex-symbols"; }
{
name = "luasnip";
option = { show_autosnippets = true; };
}
{ name = "cmp-spell"; }
{ name = "cmp-rg"; }
{ name = "path"; }
{ name = "buffer"; }
];
snippet.expand = "luasnip";
mappingPresets = [ "insert" "cmdline" ];
mapping = {
"<CR>" = "cmp.mapping.confirm({ select = true })";
"<Tab>" = {
modes = [ "i" "s" ];
action = ''
function(fallback)
local luasnip = require('luasnip')
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expandable() then
luasnip.expand()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,28 @@
{ config, pkgs, lib, inputs, ... }:
with lib;
let cfg = config.programs.riff;
in {
options.programs.riff = {
enable = mkEnableOption "riff";
direnv = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable direnv support
'';
};
};
config = mkIf cfg.enable {
home.packages = [ inputs.riff.packages.${pkgs.system}.riff ];
xdg.configFile."direnv/lib/riff.sh" = mkIf cfg.direnv {
executable = true;
text = ''
use_riff() {
watch_file Cargo.toml watch_file Cargo.lock
eval "$(riff --offline print-dev-env)"
}
'';
};
};
}

View file

@ -0,0 +1,23 @@
{ pkgs, lib, config, ... }:
with lib;
let cfg = config.programs.v.rust;
in {
options.programs.v.rust = { enable = mkEnableOption "rust"; };
config = mkIf cfg.enable {
home = {
packages = with pkgs; [ rustup ];
file = {
".cargo/config.toml".text = ''
[registries.crates-io]
protocol = "sparse"
[build]
rustc-wrapper = "${pkgs.sccache}/bin/sccache"
'';
};
sessionPath = [ "$HOME/.cargo/bin" ];
};
};
}

View file

@ -0,0 +1,72 @@
{ config, pkgs, lib, ... }:
with lib;
let cfg = config.programs.v.vscode;
in {
options.programs.v.vscode = { enable = mkEnableOption "vscode"; };
config = mkIf cfg.enable {
programs.vscode = {
enable = true;
package = pkgs.vscode;
userSettings = {
"ltex.language" = "en-GB";
"latex-workshop.linting.chktex.enabled" = true;
"latex-workshop.latex.clean.subfolder.enabled" = true;
"latex-workshop.latex.outDir" = "%TMPDIR%/%RELATIVE_DOC%";
"editor.fontFamily" =
"'DejaVuSansMono Nerd Font', 'monospace', monospace";
"keyboard.dispatch" = "keyCode";
"rust-analyzer.server.path" = "${pkgs.rust-analyzer}/bin/rust-analyzer";
"terminal.integrated.defaultProfile.linux" = "zsh";
"nix.enableLanguageServer" = true; # Enable LSP.
"nix.serverPath" = "${pkgs.nil}/bin/nil";
"[nix]" = { "editor.defaultFormatter" = "brettm12345.nixfmt-vscode"; };
"[python]" = { "editor.formatOnType" = true; };
"rust-analyzer.checkOnSave.command" = "clippy";
"debug.allowBreakpointsEverywhere" = true;
"C_Cpp.clang_format_fallbackStyle" = "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}";
# Don't index unecessary things
"files.exclude" = {
"**/.vscode" = true;
"**/.git" = true;
"**/.svn" = true;
"**/.hg" = true;
"**/.deps" = true;
"**/CVS" = true;
"**/.DS_Store" = true;
"/bin" = true;
"/boot" = true;
"/cdrom" = true;
"/dev" = true;
"/proc" = true;
"/etc" = true;
"/nix" = true;
};
};
extensions = with pkgs.vscode-extensions;
with pkgs.v.vscode-extensions; [
brettm12345.nixfmt-vscode
codezombiech.gitignore
editorconfig.editorconfig
foxundermoon.shell-format
james-yu.latex-workshop
jnoortheen.nix-ide
matklad.rust-analyzer
mkhl.direnv
ms-vscode-remote.remote-ssh
ms-vscode.cpptools
platformio.platformio-ide
redhat.vscode-yaml
redhat.vscode-xml
tamasfe.even-better-toml
valentjn.vscode-ltex
vscodevim.vim
vadimcn.vscode-lldb
xaver.clang-format
sumneko.lua
davidlday.languagetool-linter
];
};
};
}

View file

@ -0,0 +1,3 @@
{ ... }: {
imports = [ ./meta.nix ./nginx.nix ./dns.nix ./flood.nix ./gnome ./unpackerr.nix ./vault.nix ];
}

View file

@ -0,0 +1,110 @@
{ config, pkgs, lib, hosts, flat_hosts, ... }:
# DNS Module to set up Unbound DNS with all my hosts in the config
# Used for DNS Servers and my laptop
with lib;
let
inherit (builtins) filter hasAttr attrNames;
domains = attrNames hosts;
ipv4Host = filter (hasAttr "ip") flat_hosts;
ipv6Hosts = filter (hasAttr "ip6") flat_hosts;
localData = { hostname, realm, ip, ... }: ''"${hostname}.${realm}. A ${ip}"'';
local6Data = { hostname, realm, ip6, ... }:
''"${hostname}.${realm}. AAAA ${ip6}"'';
ptrData = { hostname, realm, ip, ... }: ''"${ip} ${hostname}.${realm}"'';
ptr6Data = { hostname, realm, ip6, ... }: ''"${ip6} ${hostname}.${realm}"'';
cfg = config.services.v.dns;
in
{
options.services.v.dns = {
enable = mkEnableOption "v.dns";
openFirewall = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to open port 53 in the firwall for unbound dns
And `services.prometheus.exporters.unbound.port` for metrics (if enabled).
'';
};
enableMetrics = mkOption {
type = types.bool;
default = cfg.mode == "server";
description = ''
Enable prometheus metrics
'';
};
mode = mkOption {
type = types.strMatching "^(server|laptop)$";
default = "laptop";
description = ''
Whether to configure the DNS in server mode (listen on all interfaces) or laptop mode (just on localhost)
'';
};
};
config = mkIf cfg.enable {
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
services.prometheus.exporters.unbound = mkIf cfg.enableMetrics {
enable = true;
inherit (cfg) openFirewall;
inherit (config.services.unbound) group;
controlInterface = config.services.unbound.localControlSocketPath;
};
services.unbound = {
enable = true;
package = pkgs.v.unbound;
localControlSocketPath = mkIf cfg.enableMetrics "/run/unbound/unbound.socket";
settings = {
server = mkMerge [
{
use-syslog = "yes";
module-config = ''"validator iterator"'';
local-zone =
map (localdomain: ''"${localdomain}}." transparent'') domains;
local-data = (map localData ipv4Host) ++ (map local6Data ipv6Hosts);
local-data-ptr = (map ptrData ipv4Host) ++ (map ptr6Data ipv6Hosts);
private-address = [
"127.0.0.0/8"
"10.0.0.0/8"
"::ffff:a00:0/104"
"172.16.0.0/12"
"::ffff:ac10:0/108"
"169.254.0.0/16"
"::ffff:a9fe:0/112"
"192.168.0.0/16"
"::ffff:c0a8:0/112"
"fd00::/8"
"fe80::/10"
];
}
(mkIf (cfg.mode == "server") {
interface-automatic = "yes";
interface = [ "0.0.0.0" "::0" ];
access-control = [
"127.0.0.1/32 allow_snoop"
"::1 allow_snoop"
"10.42.0.0/16 allow"
"127.0.0.0/8 allow"
"192.168.0.0/23 allow"
"192.168.2.0/24 allow"
"::1/128 allow"
];
})
(mkIf (cfg.mode == "laptop") {
interface = [ "127.0.0.1" "::1" ];
access-control = [ "127.0.0.1/32 allow_snoop" "::1 allow_snoop" ];
})
];
};
};
};
}

View file

@ -0,0 +1,153 @@
{ config, pkgs, lib, ... }:
with lib;
let cfg = config.services.flood;
in {
options.services.flood = {
enable = mkEnableOption "flood";
user = mkOption {
default = "flood";
type = types.str;
description = ''
User account under which flood runs.
'';
};
group = mkOption {
type = types.str;
default = "rtorrent";
description = ''
Group under which flood runs.
Flood needs to have the correct permissions if accessing rtorrent through the socket.
'';
};
package = mkOption {
type = types.package;
default = pkgs.flood;
defaultText = "pkgs.flood";
description = ''
The flood package to use.
'';
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
description = ''
Address flood binds to.
'';
};
port = mkOption {
type = types.port;
default = 3000;
description = ''
The flood web port.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Whether to open the firewall for the port in <option>services.flood.port</option>.
'';
};
rpcSocket = mkOption {
type = types.str;
readOnly = true;
default = "/run/rtorrent/rpc.sock";
description = ''
RPC socket path.
(Only used when auth=none).
'';
};
dataDir = mkOption {
type = types.str;
default = "/var/lib/flood";
description = ''
The directory where flood stores its data files.
'';
};
downloadDir = mkOption {
type = types.str;
default = "/var/lib/rtorrent/download";
description = ''
Root directory for downloaded files.
'';
};
authMode = mkOption {
type = types.str;
default = "none";
description = ''
Access control and user management method.
Either 'default' or 'none'.
'';
};
ssl = mkOption {
type = types.bool;
default = false;
description = ''
Enable SSL.
key.pem and fullchain.pem needed in runtime directory.
'';
};
baseURI = mkOption {
type = types.str;
default = "/";
description = ''
This URI will prefix all of Flood's HTTP requests
'';
};
};
config = mkIf cfg.enable {
# Create group if set to default
users.groups = mkIf (cfg.group == "rtorrent") { rtorrent = { }; };
# Create user if set to default
users.users = mkIf (cfg.user == "flood") {
flood = {
inherit (cfg) group;
shell = pkgs.bashInteractive;
home = cfg.dataDir;
description = "flood Daemon user";
isSystemUser = true;
};
};
# Open firewall if option is set to do so.
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
# The actual service
systemd.services.flood = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
description = "flood system service";
serviceConfig = {
User = cfg.user;
Group = cfg.group;
Type = "simple";
Restart = "on-failure";
WorkingDirectory = cfg.dataDir;
ExecStart =
"${cfg.package}/bin/flood --baseuri ${cfg.baseURI} --rundir ${cfg.dataDir} --host ${cfg.host} --port ${
toString cfg.port
} ${
if cfg.ssl then "--ssl" else ""
} --auth ${cfg.authMode} --rtsocket ${cfg.rpcSocket} --allowedpath ${cfg.downloadDir}";
};
};
# This is needed to create the dataDir with the correct permissions.
systemd.tmpfiles.rules =
[ "d '${cfg.dataDir}' 0755 ${cfg.user} ${cfg.group} -" ];
};
}

View file

@ -0,0 +1,70 @@
{ config, pkgs, lib, ... }:
with lib;
let cfg = config.services.v.gnome;
in {
options.services.v.gnome = {
enable = mkEnableOption "v.gnome";
hm = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable home manager integration to set default dconf values
'';
};
};
config = mkIf cfg.enable {
services = {
xserver = {
enable = true;
excludePackages = [ pkgs.xterm ];
# Configure keymap in X11
layout = "us";
xkbVariant = "altgr-intl";
# Enable the GNOME Desktop Environment.
displayManager.gdm.enable = true;
desktopManager.gnome.enable = true;
};
udev.packages = with pkgs; [ gnome.gnome-settings-daemon ];
dbus.enable = true;
udisks2.enable = true;
};
# Add Home-manager dconf stuff
home-manager.sharedModules = mkIf cfg.hm [ ./hm.nix ];
environment.gnome.excludePackages =
(with pkgs; [ gnome-photos gnome-tour gnome-connections ])
++ (with pkgs.gnome; [
atomix # puzzle game
epiphany # web browser
geary # email reader
gedit # text editor
gnome-calendar
gnome-clocks
gnome-contacts
gnome-maps
gnome-music
gnome-notes
gnome-terminal
gnome-weather
hitori # sudoku game
iagno # go game
simple-scan # document scanner
tali # poker game
totem # video player
]);
# Services required for gnome
programs.dconf.enable = true;
# Extra gnome packages
environment.systemPackages = with pkgs; [
gnome.gnome-tweaks
gnome.gnome-boxes
];
};
}

View file

@ -0,0 +1,132 @@
{ lib, ... }:
with lib.hm.gvariant;
let
inherit (builtins) attrNames map;
inherit (lib.attrsets) mapAttrs' nameValuePair;
generate_custom_keybindings = binds:
{
"org/gnome/settings-daemon/plugins/media-keys" = {
custom-keybindings = map (name:
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${name}/")
(attrNames binds);
};
} // mapAttrs' (name:
nameValuePair
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${name}")
binds;
in {
xdg.mimeApps.enable = true;
xdg.mimeApps.defaultApplications = {
"text/plain" = "org.gnome.TextEditor.desktop";
"application/pdf" = "org.gnome.Evince.desktop";
# Firefox
"text/html" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"x-scheme-handler/chrome" = "firefox.desktop";
"application/x-extension-htm" = "firefox.desktop";
"application/x-extension-shtml" = "firefox.desktop";
"application/xhtml+xml" = "firefox.desktop";
"application/x-extension-xhtml" = "firefox.desktop";
"application/x-extension-xht" = "firefox.desktop";
"application/x-extension-html" = "firefox.desktop";
# Images
"image/bmp" = "org.gnome.eog.desktop";
"image/gif" = "org.gnome.eog.desktop";
"image/jpg" = "org.gnome.eog.desktop";
"image/pjpeg" = "org.gnome.eog.desktop";
"image/png" = "org.gnome.eog.desktop";
"image/tiff" = "org.gnome.eog.desktop";
"image/webp" = "org.gnome.eog.desktop";
"image/x-bmp" = "org.gnome.eog.desktop";
"image/x-gray" = "org.gnome.eog.desktop";
"image/x-icb" = "org.gnome.eog.desktop";
"image/x-ico" = "org.gnome.eog.desktop";
"image/x-png" = "org.gnome.eog.desktop";
"image/x-portable-anymap" = "org.gnome.eog.desktop";
"image/x-portable-bitmap" = "org.gnome.eog.desktop";
"image/x-portable-graymap" = "org.gnome.eog.desktop";
"image/x-portable-pixmap" = "org.gnome.eog.desktop";
"image/x-xbitmap" = "org.gnome.eog.desktop";
"image/x-xpixmap" = "org.gnome.eog.desktop";
"image/x-pcx" = "org.gnome.eog.desktop";
"image/svg+xml" = "org.gnome.eog.desktop";
"image/svg+xml-compressed" = "org.gnome.eog.desktop";
"image/vnd.wap.wbmp" = "org.gnome.eog.desktop";
"image/x-icns" = "org.gnome.eog.desktop";
};
dconf.settings = {
"org/gnome/desktop/input-sources" = {
sources = [ (mkTuple [ "xkb" "us+altgr-intl" ]) ];
xkb-options = [ "terminate:ctrl_alt_bksp" ];
};
"org/gnome/desktop/peripherals/touchpad" = {
tap-to-click = true;
two-finger-scrolling-enabled = true;
};
"org/gnome/mutter" = {
attach-modal-dialogs = true;
dynamic-workspaces = false;
edge-tiling = true;
focus-change-on-pointer-rest = true;
workspaces-only-on-primary = true;
};
"org/gnome/mutter/keybindings" = {
toggle-tiled-left = [ "<Super>bracketleft" ];
toggle-tiled-right = [ "<Super>bracketright" ];
};
"org/gnome/shell/keybindings" = { toggle-overview = [ "<Super>d" ]; };
"org/gnome/desktop/interface" = { color-scheme = "prefer-dark"; };
"org/gnome/desktop/wm/preferences" = {
auto-raise = false;
num-workspaces = 6;
focus-mode = "sloppy";
};
"org/gnome/desktop/wm/keybindings" = {
raise-or-lower = [ "<Super>s" ];
switch-applications = [ "<Super>Tab" ];
switch-applications-backward = [ "<Super>Tab" ];
move-to-workspace-1 = [ "<Shift><Super>1" ];
move-to-workspace-2 = [ "<Shift><Super>2" ];
move-to-workspace-3 = [ "<Shift><Super>3" ];
move-to-workspace-4 = [ "<Shift><Super>4" ];
move-to-workspace-5 = [ "<Shift><Super>5" ];
move-to-workspace-6 = [ "<Shift><Super>6" ];
switch-to-workspace-1 = [ "<Super>1" ];
switch-to-workspace-2 = [ "<Super>2" ];
switch-to-workspace-3 = [ "<Super>3" ];
switch-to-workspace-4 = [ "<Super>4" ];
switch-to-workspace-5 = [ "<Super>5" ];
switch-to-workspace-6 = [ "<Super>6" ];
toggle-fullscreen = [ "<Super><Shift>M" ];
toggle-maximized = [ "<Super>m" ];
close = [ "<Super>Q" ];
};
"org/gnome/tweaks" = { show-extensions-notice = false; };
"org/gnome/boxes" = { first-run = false; };
} // generate_custom_keybindings {
"terminal" = {
binding = "<Super>Return";
command = "kgx";
name = "Open Terminal";
};
"firefox" = {
binding = "<Super>f";
command = "firefox";
name = "Open Firefox";
};
};
}

View file

@ -0,0 +1,43 @@
{ lib, ... }:
with lib;
let
exposesOpts = {
options = {
domain = mkOption {
type = types.str;
example = "<name>.example.com";
description = ''
The domain under which this service should be available
'';
};
port = mkOption {
type = types.int;
default = 80;
example = 4242;
description = ''
The port under which the service runs on the host
'';
};
};
};
in
{
options.meta = {
exposes = mkOption {
type = with types; attrsOf (submodule exposesOpts);
description = ''
Exposed services
'';
};
ipv4 = mkOption {
type = types.str;
description = ''
Own IPv4 Address
'';
};
};
config = { };
}

View file

@ -0,0 +1,32 @@
{ lib, hosts, config, ... }:
with lib;
let cfg = config.services.v.nginx;
in {
options.services.v.nginx.autoExpose =
mkEnableOption "generate vhosts";
config =
let
proxy = url: {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = url;
proxyWebsockets = true;
};
};
hosts' =
filter (hasAttr "exposes") (attrValues hosts.${config.networking.domain});
exposes = { ip, exposes, ... }:
map ({ domain, port ? 80 }: { inherit ip domain port; }) (attrValues exposes);
mkVhost = { ip, domain, port }: {
"${domain}" = proxy "http://${ip}:${toString port}";
};
vhosts = foldr (el: acc: acc // mkVhost el) { } (concatMap exposes hosts');
in
mkIf cfg.autoExpose {
services.nginx.virtualHosts = vhosts;
};
}

View file

@ -0,0 +1,328 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.unpackerr;
mkStarrOptions = { name, url }: {
url = mkOption {
type = types.str;
default = "";
example = "${url}";
description = ''
The URL to access ${name}
'';
};
apiKey = mkOption {
type = types.str;
default = "";
description = ''
The API key for accessing ${name}
'';
};
paths = mkOption {
type = types.str;
default = "";
example = "/downloads,/moreDownloads";
description = ''
List of paths where content is downloaded for ${name}
'';
};
protocols = mkOption {
type = types.str;
default = "torrent";
example = "torrent,usenet";
description = ''
Protocols to process
'';
};
timeout = mkOption {
type = types.str;
default = "10s";
description = ''
How long to wait for ${name} to respond
'';
};
deleteOrginal = mkOption {
type = types.bool;
default = false;
description = ''
Delete archives after import?
Recommend not setting this to true
'';
};
deleteDelay = mkOption {
type = types.str;
default = "5m";
description = ''
Extracts are deleted this long after import. `-1` to disable.
'';
};
};
in
{
options.services.unpackerr = {
enable = mkEnableOption "unpackerr";
user = mkOption {
default = "unpackerr";
type = types.str;
description = ''
User account under which unpackerr runs.
'';
};
group = mkOption {
type = types.str;
default = "unpackerr";
description = ''
Group under which unpackerr runs.
'';
};
package = mkOption {
type = types.package;
default = pkgs.unpackerr;
defaultText = "pkgs.unpackerr";
description = ''
The unpackerr package to use.
'';
};
debug = mkOption {
type = types.bool;
default = false;
description = ''
Turns on more logs.
'';
};
interval = mkOption {
type = types.str;
default = "2m";
description = ''
How often apps are polled, recommended 1m to 5m
'';
};
startDelay = mkOption {
type = types.str;
default = "1m";
description = ''
Files are queued at least this long before extraction
'';
};
retryDelay = mkOption {
type = types.str;
default = "5m";
description = ''
Failed extractions are retried after at least this long
'';
};
maxRetries = mkOption {
type = types.int;
default = 3;
description = ''
Times to retry failed extractions. `0` = unlimited.
'';
};
parallel = mkOption {
type = types.int;
default = 1;
description = ''
Concurrent extractions, 1 is recommended.
'';
};
fileMode = mkOption {
type = types.str;
default = "0644";
description = ''
Extracted files are written with this mode
'';
};
dirMode = mkOption {
type = types.str;
default = "0755";
description = ''
Extracted folders are written with this mode
'';
};
sonarr = mkStarrOptions {
name = "Sonarr";
url = "http://localhost:8989";
};
radarr = mkStarrOptions {
name = "Radarr";
url = "http://localhost:7878";
};
lidarr = mkStarrOptions {
name = "Lidarr";
url = "http://localhost:8686";
};
readarr = mkStarrOptions {
name = "Readarr";
url = "http://localhost:8787";
};
folder = {
path = mkOption {
type = types.str;
default = "";
description = ''
folder path, not for Starr apps.
'';
};
extractPath = mkOption {
type = types.str;
default = "";
description = ''
Where to extract to, Defaults to <option>services.unpackerr.folder.path</option>.
'';
};
deleteAfter = mkOption {
type = types.str;
default = "";
example = "10m";
description = ''
Delete extracted files and/or archives after this duration, `0` to disable.
'';
};
deleteOrginal = mkOption {
type = types.bool;
default = false;
description = ''
Delete archives after extraction
'';
};
deleteFiles = mkOption {
type = types.bool;
default = false;
description = ''
Delete extracted files after successful extraction
'';
};
moveBack = mkOption {
type = types.bool;
default = false;
description = ''
Move extracted items back into original folder
'';
};
};
extraConfig = mkOption {
type = types.attrs;
default = { };
description = ''
Extra environment variables
'';
example = { UN_WEBHOOK_0_URL = "http://example.com"; };
};
environmentFile = mkOption {
type = types.nullOr types.path;
default = null;
description = lib.mdDoc ''
Environment file (see `systemd.exec(5)`
"EnvironmentFile=" section for the syntax) to define variables for unpackerr.
This option can be used to safely include secret keys into the unpackerr configuration.
'';
};
};
config = mkIf cfg.enable {
# Create group if set to default
users.groups = mkIf (cfg.group == "unpackerr") { unpackerr = { }; };
# Create user if set to default
users.users = mkIf (cfg.user == "unpackerr") {
unpackerr = {
inherit (cfg) group;
shell = pkgs.bashInteractive;
createHome = false;
description = "unpackerr Daemon user";
isSystemUser = true;
};
};
# The actual service
systemd.services.unpackerr = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
description = "unpackerr system service";
# Filter out all unset variables else unpackerr complains
environment = filterAttrs (_n: v: stringLength v > 0)
{
# General options
UN_DEBUG = "${toString cfg.debug}";
UN_INTERVAL = "${cfg.interval}";
UN_START_DELAY = "${cfg.startDelay}";
UN_RETRY_DELAY = "${cfg.retryDelay}";
UN_MAX_RETRIES = "${toString cfg.maxRetries}";
UN_PARALLEL = "${toString cfg.parallel}";
UN_FILE_MODE = "${cfg.fileMode}";
UN_DIR_MODE = "${cfg.dirMode}";
# Sonarr
UN_SONARR_0_URL = "${cfg.sonarr.url}";
UN_SONARR_0_API_KEY = "${cfg.sonarr.apiKey}";
UN_SONARR_0_PATHS_0 = "${cfg.sonarr.paths}";
UN_SONARR_0_PROTOCOLS = "${cfg.sonarr.protocols}";
UN_SONARR_0_TIMEOUT = "${cfg.sonarr.timeout}";
UN_SONARR_0_DELETE_ORIG = "${toString cfg.sonarr.deleteOrginal}";
UN_SONARR_0_DELETE_DELAY = "${cfg.sonarr.deleteDelay}";
# Radarr
UN_RADARR_0_URL = "${cfg.radarr.url}";
UN_RADARR_0_API_KEY = "${cfg.radarr.apiKey}";
UN_RADARR_0_PATHS_0 = "${cfg.radarr.paths}";
UN_RADARR_0_PROTOCOLS = "${cfg.radarr.protocols}";
UN_RADARR_0_TIMEOUT = "${cfg.radarr.timeout}";
UN_RADARR_0_DELETE_ORIG = "${toString cfg.radarr.deleteOrginal}";
UN_RADARR_0_DELETE_DELAY = "${cfg.radarr.deleteDelay}";
# Lidarr
UN_LIDARR_0_URL = "${cfg.lidarr.url}";
UN_LIDARR_0_API_KEY = "${cfg.lidarr.apiKey}";
UN_LIDARR_0_PATHS_0 = "${cfg.lidarr.paths}";
UN_LIDARR_0_PROTOCOLS = "${cfg.lidarr.protocols}";
UN_LIDARR_0_TIMEOUT = "${cfg.lidarr.timeout}";
UN_LIDARR_0_DELETE_ORIG = "${toString cfg.lidarr.deleteOrginal}";
UN_LIDARR_0_DELETE_DELAY = "${cfg.lidarr.deleteDelay}";
# Readarr
UN_READARR_0_URL = "${cfg.readarr.url}";
UN_READARR_0_API_KEY = "${cfg.readarr.apiKey}";
UN_READARR_0_PATHS_0 = "${cfg.readarr.paths}";
UN_READARR_0_PROTOCOLS = "${cfg.readarr.protocols}";
UN_READARR_0_TIMEOUT = "${cfg.readarr.timeout}";
UN_READARR_0_DELETE_ORIG = "${toString cfg.readarr.deleteOrginal}";
UN_READARR_0_DELETE_DELAY = "${cfg.readarr.deleteDelay}";
# Folder
UN_FOLDER_0_PATH = "${cfg.folder.path}";
UN_FOLDER_0_EXTRACT_PATH = "${cfg.folder.extractPath}";
UN_FOLDER_0_DELETE_AFTER = "${cfg.folder.deleteAfter}";
UN_FOLDER_0_DELETE_ORIGINAL = "${toString cfg.folder.deleteOrginal}";
UN_FOLDER_0_DELETE_FILES = "${toString cfg.folder.deleteFiles}";
UN_FOLDER_0_MOVE_BACK = "${toString cfg.folder.moveBack}";
} // cfg.extraConfig;
serviceConfig = {
User = cfg.user;
Group = cfg.group;
Type = "simple";
Restart = "on-failure";
ExecStart = "${cfg.package}/bin/unpackerr";
} // optionalAttrs (cfg.environmentFile != null) {
EnvironmentFile = cfg.environmentFile;
};
};
};
}

View file

@ -0,0 +1,125 @@
{ config, pkgs, lib, flat_hosts, inputs, ... }:
with lib;
let
cfg = config.services.v.vault;
hostIP = config.meta.ipv4;
# Find all vault hosts that do not have the same IP as the current host
vault_hosts =
filter ({ tags ? [ ], ip ? "", ... }: (elem "vault" tags) && (ip != hostIP))
flat_hosts;
cluster_config = concatStrings (map
({ ip, ... }: ''
retry_join {
leader_api_addr = "http://${ip}:${toString cfg.port}"
}
'')
vault_hosts);
in
{
options.services.v.vault = {
enable = mkEnableOption "v's vault";
node_id = mkOption {
type = types.str;
description = lib.mdDoc ''
The cluster node id of this node
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to open port `port` and `clusterPort` in the firewall for vault
'';
};
port = mkOption {
type = types.int;
default = 8200;
description = lib.mdDoc ''
The port vault listens on
**note:** this has to be the same for all nodes in a cluster
'';
};
clusterPort = mkOption {
type = types.int;
default = 8201;
description = lib.mdDoc ''
The cluster port vault listens on
**note:** this has to be the same for all nodes in a cluster
'';
};
autoUnseal = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to auto-unseal this vault
'';
};
autoUnsealKeysFile = mkOption {
type = types.str;
default = null;
example = "/var/lib/vault-unseal/keys.json";
description = lib.mdDoc ''
auto unseal keys to use, has to be a json file with the following structure
```json
{
keys = [ key_1, ..., key_n ]
}
```
'';
};
};
config = mkIf cfg.enable {
assertions = [{
assertion = cfg.autoUnseal -> (cfg.autoUnsealKeysFile != null);
message = "If autoUnseal is enabled, a token path is required!";
}];
networking.firewall.allowedTCPPorts =
mkIf cfg.openFirewall [ cfg.port cfg.clusterPort ];
services.vault = {
enable = true;
# bin version includes the UI
package = pkgs.vault-bin;
address = "0.0.0.0:${toString cfg.port}";
storageBackend = "raft";
storagePath = "/var/lib/vault-raft";
storageConfig = ''
node_id = "${cfg.node_id}"
'' + cluster_config;
extraConfig = ''
ui = true
disable_mlock = true
api_addr = "http://${hostIP}:${toString cfg.port}"
cluster_addr = "http://${hostIP}:${toString cfg.clusterPort}"
'';
};
systemd.services.vault-unseal = mkIf cfg.autoUnseal {
description = "Vault unseal service";
wantedBy = [ "multi-user.target" ];
after = [ "vault.service" ];
environment = {
VAULT_ADDR = "http://localhost:${toString cfg.port}";
VAULT_KEY_FILE = cfg.autoUnsealKeysFile;
};
serviceConfig = {
User = "vault";
Group = "vault";
Type = "simple";
Restart = "on-failure";
ExecStart = "${
inputs.vault-unseal.packages.${pkgs.system}.default
}/bin/vault-unseal";
};
};
};
}

View file

@ -0,0 +1,55 @@
{ config, pkgs, lib, ... }: {
imports = [ ./laura.nix ./vivian.nix ./jonathan.nix ];
# Setup ZSH to use grml config
programs.zsh = {
enable = true;
enableCompletion = true;
syntaxHighlighting.enable = true;
interactiveShellInit = ''
source "${pkgs.grml-zsh-config}/etc/zsh/zshrc"
export FZF_DEFAULT_COMMAND="${pkgs.ripgrep}/bin/rg --files --follow"
source "${pkgs.fzf}/share/fzf/key-bindings.zsh"
source "${pkgs.fzf}/share/fzf/completion.zsh"
eval "$(${pkgs.zoxide}/bin/zoxide init zsh)"
'';
# otherwise it'll override the grml prompt
promptInit = "";
};
environment.pathsToLink = [ "/share/zsh" ];
# Install Neovim and set it as alias for vi(m)
programs.neovim = {
enable = true;
viAlias = true;
vimAlias = true;
defaultEditor = true;
};
# Disable sudo prompt for `wheel` users.
security.sudo.wheelNeedsPassword = lib.mkDefault false;
# Configure the root account
users.extraUsers.root = {
# Allow my SSH keys for logging in as root.
openssh.authorizedKeys.keys =
config.users.extraUsers.vivian.openssh.authorizedKeys.keys;
# Also use zsh for root
shell = pkgs.zsh;
};
# Setup packages available everywhere
environment.systemPackages = with pkgs; [
fzf
git
htop
ncdu
psmisc
ripgrep
rsync
tmux
zoxide
tmux
];
}

View file

@ -0,0 +1,13 @@
{ pkgs, ... }: {
users.extraUsers.jonathan = {
isNormalUser = true;
shell = pkgs.zsh;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOAXOTU6E06zjK/zkzlSPhTG35PoNRYgTCStEPUYyjeE jonathan@kili"
];
extraGroups = [ ];
};
}

View file

@ -0,0 +1,14 @@
{ pkgs, ... }: {
users.extraUsers.laura = {
isNormalUser = true;
shell = pkgs.zsh;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBIlFUUXbwOkhNUjoA6zueTdRuaylgpgFqSe/xWGK9zb laura@zmeura"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBVkk9/80askWhInQk03JMntF6SThAYkFZNm+lIGt4E7 laura@mura"
];
extraGroups = [ ];
};
}

View file

@ -0,0 +1,48 @@
{ pkgs, ... }: {
# The block that specifies my user account.
users.extraUsers.vivian = {
uid = 1000;
# This account is intended for a non-system user.
isNormalUser = true;
# My default shell
shell = pkgs.zsh;
# My SSH keys.
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICBhJAp7NWlHgwDYd2z6VNROy5RkeZHRINFLsFvwT4b3 vivian@bastion"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMMbdjysLnmwJD5Fs/SjBPstdIQNUxy8zFHP0GlhHMJB vivian@bastion"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIfooZjMWXvXZu1ReOEACDZ0TMb2WJRBSOLlWE8y6fUh vivian@aoife"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBMTCUjDbDjAiEKbKmLPavuYM0wJIBdjgytLsg1uWuGc vivian@nord"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIM3TqXaApX2JZsgfZd7PKVFMecDgqTHKibpSzgdXNpYAAAAABHNzaDo= solov2-le"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID+HbsgJTQS6pvnMEI5NPKjIf78z+9A7CTIt3abi+PS6 vivian@eevee"
];
# Make me admin
extraGroups =
[ "systemd-journal" "wheel" "networkmanager" "libvirtd" "dialout" ];
};
home-manager.users.vivian = {
programs = {
home-manager.enable = true;
v.git.enable = true;
tmux = {
enable = true;
shortcut = "b";
terminal = "screen-256color";
clock24 = true;
};
bat.enable = true;
};
home = {
username = "vivian";
homeDirectory = "/home/vivian";
stateVersion = "23.05";
};
};
}

2
nixos/hosts/README.md Normal file
View file

@ -0,0 +1,2 @@
# NixOS Hosts
Each folder here is a separate geographical location, with `thalassa` being for roaming devices like laptops

5
nixos/hosts/default.nix Normal file
View file

@ -0,0 +1,5 @@
{
hades = import ./hades;
olympus = import ./olympus;
thalassa = import ./thalassa;
}

View file

@ -0,0 +1,22 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, ... }:
{
imports = [ ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.11"; # Did you read the comment?
# Additional packages
environment.systemPackages = with pkgs; [ ];
networking.firewall.allowedTCPPorts = [ ];
}

View file

@ -0,0 +1,93 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, config, ... }:
let vs = config.vault-secrets.secrets;
in {
imports = [ ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.11"; # Did you read the comment?
# Additional packages
environment.systemPackages = with pkgs; [ ];
vault-secrets.secrets.attic = { services = [ "atticd" ]; };
services.postgresql = {
enable = true;
package = pkgs.postgresql_15;
ensureDatabases = [ "atticd" ];
ensureUsers = [{
name = "atticd";
ensurePermissions = {
"DATABASE atticd" = "ALL PRIVILEGES";
"schema public" = "ALL";
};
}];
};
services.atticd = {
enable = true;
credentialsFile = "${vs.attic}/environment";
settings = {
listen = "[::]:8080";
allowed-hosts = [ "attic.xirion.net" ];
api-endpoint = "https://attic.xirion.net/";
require-proof-of-possession = false;
garbage-collection = {
interval = "12 hours";
default-retention-period = "1 month";
};
compression = {
type = "zstd";
level = 8;
};
database.url = "postgresql://atticd?host=/run/postgresql";
storage = {
type = "s3";
region = "hades";
bucket = "attic";
endpoint = "http://garage.hades:3900";
};
# Data chunking
#
# Warning: If you change any of the values here, it will be
# difficult to reuse existing chunks for newly-uploaded NARs
# since the cutpoints will be different. As a result, the
# deduplication ratio will suffer for a while after the change.
chunking = {
# The minimum NAR size to trigger chunking
#
# If 0, chunking is disabled entirely for newly-uploaded NARs.
# If 1, all NARs are chunked.
nar-size-threshold = 64 * 1024; # 64 KiB
# The preferred minimum size of a chunk, in bytes
min-size = 16 * 1024; # 16 KiB
# The preferred average size of a chunk, in bytes
avg-size = 64 * 1024; # 64 KiB
# The preferred maximum size of a chunk, in bytes
max-size = 256 * 1024; # 256 KiB
};
};
};
networking.firewall.allowedTCPPorts = [ 8080 ];
}

View file

@ -0,0 +1,29 @@
{ pkgs, lib, ... }: {
networking.interfaces.eth0.useDHCP = true;
# mosh ssh
programs.mosh.enable = true;
environment.systemPackages = with pkgs; [
cachix
clang
direnv
git-crypt
nix-update
pinentry-curses
ripgrep
rsync
rustup
tmux
vault
];
environment.noXlibs = lib.mkForce false;
system.stateVersion = "22.11";
programs.gnupg.agent = {
enable = true;
pinentryFlavor = "curses";
};
}

View file

@ -0,0 +1,14 @@
_: {
system.stateVersion = "22.11";
networking.interfaces.eth0.useDHCP = true;
fileSystems."/mnt/storage" = {
device = "storage:/mnt/storage";
fsType = "nfs";
};
services.bazarr = {
enable = true;
openFirewall = true;
};
}

View file

@ -0,0 +1,38 @@
{ config, pkgs, ... }:
let vs = config.vault-secrets.secrets;
in {
system.stateVersion = "21.05";
networking.interfaces.eth0.useDHCP = true;
networking.firewall.allowedTCPPorts = [ config.services.postgresql.port ];
vault-secrets.secrets.database = {
user = "postgres";
group = "postgres";
services = [ "postgresql" ];
};
services.postgresql = {
enable = true;
package = pkgs.postgresql_13;
enableTCPIP = true;
extraPlugins = [ ];
initdbArgs = [
"--encoding 'UTF-8'"
"--lc-collate='en_US.UTF-8'"
"--lc-ctype='en_US.UTF-8'"
];
authentication = ''
host all all 192.168.0.1/23 md5
host all all 10.10.10.0/24 md5
'';
initialScript = "${vs.database}/initialScript";
settings = {
shared_preload_libraries = "pg_stat_statements";
"pg_stat_statements.track" = "all";
"pg_stat_statements.max" = 10000;
track_activity_query_size = 2048;
};
};
}

View file

@ -0,0 +1,172 @@
{
"opnsense" = {
ip = "192.168.0.1";
mac = "00:0d:b9:56:b1:d8";
nix = false;
};
"nyx-bmc" = {
ip = "192.168.0.99";
mac = "d0:50:99:f3:fa:42";
nix = false;
};
"nyx" = {
ip = "192.168.0.100";
mac = "d0:50:99:de:99:4c";
nix = false;
};
"unifi" = {
ip = "192.168.0.101";
mac = "5a:00:b7:6c:d1:e2";
};
"plex" = {
ip = "192.168.0.102";
mac = "00:0c:29:a1:4e:28";
nix = false;
};
"vault-0" = {
ip = "192.168.0.103";
mac = "7A:14:15:ED:D1:E6";
tags = [ "vault" ];
};
"pmm" = {
ip = "192.168.0.104";
mac = "7A:A3:59:1D:69:07";
};
"overseerr" = {
ip = "192.168.0.105";
mac = "8E:21:7F:88:3A:83";
};
"tautulli" = {
ip = "192.168.0.106";
mac = "BE:30:DB:F8:C6:55";
};
"dns-1" = {
ip = "192.168.0.107";
mac = "12:84:3B:E0:8A:A0";
profile = "dns";
tags = [ "networking" ];
};
"dns-2" = {
ip = "192.168.0.108";
mac = "56:C3:9C:A5:41:81";
profile = "dns";
tags = [ "networking" ];
};
"MariaDB" = {
ip = "192.168.0.109";
mac = "00:0c:29:23:4f:12";
nix = false;
};
"bitwarden_rs" = {
ip = "192.168.0.110";
mac = "00:0c:29:f5:98:00";
nix = false;
};
"rtorrent" = {
ip = "192.168.0.111";
mac = "7a:5f:9b:62:49:91";
};
"cshub2" = {
ip = "192.168.0.113";
mac = "26:8c:f6:f4:21:76";
nix = false;
};
"bastion" = {
ip = "192.168.0.114";
mac = "66:14:8e:b2:50:c4";
};
"storage" = {
ip = "192.168.0.115";
mac = "00:50:56:91:0d:69";
nix = false;
};
"immich" = {
ip = "192.168.0.116";
mac = "06:8a:8e:3e:43:45";
};
"thelounge" = {
ip = "192.168.0.117";
mac = "00:0c:29:2a:69:8f";
nix = false;
};
"mail" = {
ip = "192.168.0.118";
mac = "00:50:56:91:3b:03";
nix = false;
};
"bazarr" = {
ip = "192.168.0.119";
mac = "DE:7C:32:7E:DD:A1";
};
"plex2" = {
ip = "192.168.0.120";
mac = "A2:2C:65:32:54:8A";
profile = "plex";
};
"garage" = {
ip = "192.168.0.121";
mac = "3A:19:32:A2:F8:96";
};
"nginx" = {
ip = "192.168.0.122";
mac = "52:8E:72:31:AE:AC";
};
"reverseproxy" = {
ip = "192.168.0.123";
mac = "00:0c:29:9b:10:82";
nix = false;
};
"pve-storage" = {
ip = "192.168.0.124";
mac = "d4:3d:7e:35:0a:bf";
nix = false;
};
"lucy" = {
ip = "192.168.0.125";
mac = "5E:36:04:2D:38:DF";
type = "vm";
};
"database" = {
ip = "192.168.0.126";
mac = "82:e8:71:7f:37:b4";
};
"dn42" = {
ip = "192.168.0.127";
mac = "12:fa:24:02:65:e6";
nix = false;
};
"attic" = {
ip = "192.168.0.128";
mac = "9E:AF:E9:FE:D4:D9";
};
"hassio" = {
ip = "192.168.0.129";
mac = "e6:80:32:fb:00:75";
nix = false;
};
# "docker-registry" = {
# ip = "192.168.0.130"attic, ;
# mac = "5e:0e:a6:cf:64:70";
# };
"minecraft" = {
ip = "192.168.0.131";
mac = "00:0c:29:9b:e1:c4";
nix = false;
};
# ip = "192.168.0.132";
"mastodon" = {
ip = "192.168.0.138";
mac = "52:60:8a:06:86:9c";
};
# ip = "192.168.0.140";
"archlinux" = {
ip = "192.168.0.200";
mac = "00:0c:29:e4:0d:17";
nix = false;
};
"HP781AFC" = {
ip = "192.168.0.201";
mac = "f4:ce:46:78:1a:fc";
nix = false;
};
}

View file

@ -0,0 +1,50 @@
{ pkgs, ... }: {
imports = [ ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
# Additional packages
environment.systemPackages = with pkgs; [ dig dogdns ];
services.v.dns = {
enable = true;
openFirewall = true;
mode = "server";
};
services.unbound.settings.server = {
local-zone = [
"xirion.net typetransparent"
"attic.xirion.net typetransparent"
"o.xirion.net typetransparent"
"attic.xirion.net typetransparent"
"g.xirion.net typetransparent"
"fedi-media.xirion.net typetransparent"
"hades.xirion.net typetransparent"
"requests.xirion.net typetransparent"
"ha.xirion.net typetransparent"
"mail.xirion.net typetransparent"
"plex.xirion.net typetransparent"
];
local-data = [
''"xirion.net A 192.168.0.122"''
''"attic.xirion.net A 192.168.0.122"''
''"hades.xirion.net A 192.168.0.122"''
''"o.xirion.net A 192.168.0.122"''
''"attic.xirion.net A 192.168.0.122"''
''"g.xirion.net A 192.168.0.122"''
''"fedi-media.xirion.net A 192.168.0.122"''
''"requests.xirion.net A 192.168.0.122"''
''"ha.xirion.net A 192.168.0.122"''
''"mail.xirion.net A 192.168.0.122"''
''"plex.xirion.net A 192.168.0.122"''
];
};
}

View file

@ -0,0 +1,53 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, config, ... }:
let vs = config.vault-secrets.secrets;
in {
imports = [ ];
vault-secrets.secrets.garage = { };
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.11"; # Did you read the comment?
# Additional packages
environment.systemPackages = with pkgs; [ ];
networking.firewall.allowedTCPPorts = [ 3900 3901 3902 ];
# Defines rpc_secret
systemd.services.garage.serviceConfig.EnvironmentFile = [ "${vs.garage}/environment" ];
services.garage = {
enable = true;
package = pkgs.garage_0_8;
settings = {
db_engine = "lmdb"; # Recommended for mastodon
replication_mode = "1";
compression_level = 0;
# For inter-node comms
rpc_bind_addr = "[::]:3901";
rpc_public_addr = "${config.meta.ipv4}:3901";
# Standard S3 api endpoint
s3_api = {
s3_region = "hades";
api_bind_addr = "[::]:3900";
};
# Static file serve endpoint
s3_web = {
bind_addr = "[::]:3902";
root_domain = "g.xirion.net";
};
};
};
}

View file

@ -0,0 +1,73 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, config, ... }:
let
# https://github.com/immich-app/immich/releases
# version = "1.55.1";
dataDir = "/var/lib/immich";
in
{
imports = [ ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
# Additional packages
environment.systemPackages = with pkgs; [ ];
# TODO: https://github.com/suderman/nixos/tree/main/modules/nixos/immich
fileSystems."/mnt/storage" = {
device = "storage:/mnt/storage";
fsType = "nfs";
};
# Unused uid/gid snagged from this list:
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/misc/ids.nix
ids.uids.immich = 911;
ids.gids.immich = 911;
users.groups.photos = {};
users.users.immich = {
isSystemUser = true;
group = "photos";
description = "Immich daemon user";
home = dataDir;
uid = config.ids.uids.immich;
};
users.groups.immich = { gid = config.ids.gids.immich; };
# Postgres database configuration
services.postgresql = {
enable = true;
package = pkgs.postgresql_15;
ensureUsers = [{
name = "immich";
ensurePermissions = { "DATABASE immich" = "ALL PRIVILEGES"; };
}];
ensureDatabases = [ "immich" ];
# Allow connections from any docker IP addresses
authentication = ''
host immich immich 172.16.0.0/12 md5
host all all 127.0.0.1/32 ident
'';
};
# Allow docker containers to connect
networking.firewall.allowedTCPPorts = [ config.services.postgresql.port ];
}

View file

@ -0,0 +1,75 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, ... }:
let
# Redefining the package instead of overriding as overriding GoModules seems broken
# see: https://github.com/NixOS/nixpkgs/issues/86349
nuclei-latest = pkgs.buildGoModule rec {
pname = "nuclei";
version = "2.9.2";
src = pkgs.fetchFromGitHub {
owner = "projectdiscovery";
repo = pname;
rev = "1f9a065713924b28b203e2108fc76d7a1ec49068";
hash = "sha256-QiegMoBy0gZMyQl2MRAwR14zXeh8wvVonyETdAzHbj0=";
};
vendorHash = "sha256-0JNwoBqLKH1F/0Tr8o35gCSNT/2plIjIQvZRuzAZ5P8=";
modRoot = "./v2";
subPackages = [ "cmd/nuclei/" ];
doCheck = false;
};
in
{
imports = [ ./hardware-configuration.nix ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
# Additional packages
environment.systemPackages = with pkgs; [
ffuf
gcc
go
jq
nuclei-latest
rustup
trivy
wapiti
];
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
efi.efiSysMountPoint = "/boot";
};
virtualisation.docker.enable = true;
services.mosquitto = {
enable = true;
listeners = [{
acl = [ "pattern readwrite #" ];
omitPasswordAuth = true;
settings.allow_anonymous = true;
}];
};
networking.firewall = {
enable = true;
allowedTCPPorts = [ 1883 ];
};
users.extraUsers.laura.extraGroups = [ "wheel" "docker" ];
users.extraUsers.vivian.extraGroups = [ "docker" ];
}

View file

@ -0,0 +1,44 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ lib, modulesPath, ... }:
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot = {
initrd.availableKernelModules = [
"uhci_hcd"
"ehci_pci"
"ahci"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
initrd.kernelModules = [ ];
kernelModules = [ ];
extraModulePackages = [ ];
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/749c02fd-209d-4974-917e-38b749d10ec2";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/D021-72EB";
fsType = "vfat";
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp6s18.useDHCP = lib.mkDefault true
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View file

@ -0,0 +1,107 @@
{ config, pkgs, lib, ... }:
let
vs = config.vault-secrets.secrets;
cfg = config.services.mastodon;
in
{
system.stateVersion = "21.05";
# Use DHCP with static leases
networking.interfaces.eth0.useDHCP = true;
# Better cache hits
environment.noXlibs = lib.mkForce false;
services.elasticsearch = {
enable = true;
cluster_name = "mastodon-es";
package = pkgs.elasticsearch7;
};
vault-secrets.secrets.mastodon = {
services = [ "mastodon-init-dirs" "mastodon" "mastodon-media-autoremove" ];
inherit (cfg) user group;
};
# Append the init-dirs script to add AWS/Minio secrets
systemd.services.mastodon-init-dirs.script = ''
cat >> /var/lib/mastodon/.secrets_env <<EOF
AWS_ACCESS_KEY_ID="$(cat ${vs.mastodon}/garageKeyId)"
AWS_SECRET_ACCESS_KEY="$(cat ${vs.mastodon}/garageSecretKey)"
DEEPL_API_KEY="$(cat ${vs.mastodon}/deeplAPIKey)"
EOF
'';
services.mastodon = {
enable = true;
package = pkgs.v.glitch-soc;
streamingPort = 55000;
webPort = 55001;
enableUnixSocket = false;
localDomain = "xirion.net";
trustedProxy = "192.168.0.122";
mediaAutoRemove = {
enable = true;
olderThanDays = 30;
startAt = "daily";
};
configureNginx = false;
redis.createLocally = true;
elasticsearch = {
host = "127.0.0.1";
inherit (config.services.elasticsearch) port;
};
database = {
createLocally = false;
user = "mastodon";
passwordFile = "${vs.mastodon}/db-password";
port = 5432;
name = "mastodon";
host = "192.168.0.126";
};
smtp = {
createLocally = false;
fromAddress = "mastodon@xirion.net";
host = "mail.0x76.dev";
user = "mastodon@xirion.net";
authenticate = true;
port = 587;
passwordFile = "${vs.mastodon}/smtp-password";
};
extraConfig = {
BIND = "0.0.0.0";
SINGLE_USER_MODE = "false";
EMAIL_DOMAIN_ALLOWLIST = "xirion.net";
DEFAULT_LOCALE = "en";
WEB_DOMAIN = "fedi.xirion.net";
ALTERNATE_DOMAINS = "meowy.tech";
SMTP_AUTH_METHOD = "plain";
SMTP_OPENSSL_VERIFY_MODE = "none";
RAILS_SERVE_STATIC_FILES = "false";
AUTHORIZED_FETCH = "true";
# https://github.com/cybrespace/cybrespace-meta/blob/master/s3.md;
# https://shivering-isles.com/Mastodon-and-Amazon-S3
S3_ENABLED = "true";
S3_REGION = "hades";
S3_BUCKET = "mastodon";
S3_ENDPOINT = "http://garage.hades:3900";
S3_ALIAS_HOST = "fedi-media.xirion.net";
DEEPL_PLAN = "free";
};
};
networking.firewall =
let cfg = config.services.mastodon;
in { allowedTCPPorts = [ cfg.streamingPort cfg.webPort ]; };
}

View file

@ -0,0 +1,17 @@
{ config, pkgs, ... }:
let vs = config.vault-secrets.secrets;
in {
system.stateVersion = "22.11";
networking.firewall.allowedTCPPorts = [ 9000 9001 ];
networking.interfaces.eth0.useDHCP = true;
vault-secrets.secrets.minio = { };
services.minio = {
enable = true;
rootCredentialsFile = "${vs.minio}/environment";
package = pkgs.minio_legacy_fs;
};
}

View file

@ -0,0 +1,175 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, ... }:
let
proxy = url: {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = url;
proxyWebsockets = true;
};
};
in
{
imports = [ ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
networking.firewall.allowedTCPPorts = [ 80 443 ];
security.acme = {
defaults.email = "vivian@0x76.dev";
acceptTerms = true;
preliminarySelfsigned = true;
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedBrotliSettings = true;
clientMaxBodySize = "1024m";
package = pkgs.nginxMainline;
virtualHosts = {
"ha.xirion.net" = proxy "http://192.168.0.129:8123";
"xirion.net" = {
enableACME = true;
forceSSL = true;
locations."/".extraConfig = ''
add_header Content-Type 'text/html; charset=UTF-8';
return 200 'Hello, World!';
'';
locations."= /.well-known/host-meta".extraConfig = ''
return 301 https://fedi.xirion.net$request_uri;
'';
};
# virtualHosts."blog.xirion.net" = proxy "http://10.10.10.12";
"git.xirion.net" = proxy "http://10.10.10.12";
# virtualHosts."mail.xirion.net" = proxy "http://192.168.0.118";
"o.xirion.net" = proxy "http://192.168.0.112:9000";
"g.xirion.net" = proxy "http://garage.hades:3900";
"requests.xirion.net" = proxy "http://overseerr.hades:5055";
"pass.xirion.net" = proxy "http://bitwarden_rs";
"repo.xirion.net" = proxy "http://archlinux";
"thelounge.xirion.net" = proxy "http://thelounge:9000";
"attic.xirion.net" = proxy "http://attic.hades:8080";
"tautulli.xirion.net" = proxy "http://tautulli.hades:8080";
"peepeepoopoo.xirion.net" = proxy "http://tautulli.hades:8080"; # Deprecated but Ricardo has it bookmarked already!
"registry.xirion.net" = proxy "http://docker-registry:5000"
// {
locations."/".extraConfig = ''
allow 127.0.0.1;
allow 10.42.42.0/23;
allow 10.10.10.1/24;
allow 192.168.0.0/23;
allow 80.60.83.220;
allow 83.128.154.23;
allow 62.45.26.248;
allow 195.85.167.32/29;
deny all;
'';
};
"plex.xirion.net" = {
# Since we want a secure connection, we force SSL
forceSSL = true;
enableACME = true;
extraConfig = ''
#Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause
send_timeout 100m;
# Why this is important: https://blog.cloudflare.com/ocsp-stapling-how-cloudflare-just-made-ssl-30/
ssl_stapling on;
ssl_stapling_verify on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
#Intentionally not hardened for security for player support and encryption video streams has a lot of overhead with something like AES-256-GCM-SHA384.
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
# Forward real ip and host to Plex
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $server_addr;
proxy_set_header Referer $server_addr;
proxy_set_header Origin $server_addr;
# Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones.
# Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more
client_max_body_size 100M;
# Plex headers
proxy_set_header X-Plex-Client-Identifier $http_x_plex_client_identifier;
proxy_set_header X-Plex-Device $http_x_plex_device;
proxy_set_header X-Plex-Device-Name $http_x_plex_device_name;
proxy_set_header X-Plex-Platform $http_x_plex_platform;
proxy_set_header X-Plex-Platform-Version $http_x_plex_platform_version;
proxy_set_header X-Plex-Product $http_x_plex_product;
proxy_set_header X-Plex-Token $http_x_plex_token;
proxy_set_header X-Plex-Version $http_x_plex_version;
proxy_set_header X-Plex-Nocache $http_x_plex_nocache;
proxy_set_header X-Plex-Provides $http_x_plex_provides;
proxy_set_header X-Plex-Device-Vendor $http_x_plex_device_vendor;
proxy_set_header X-Plex-Model $http_x_plex_model;
# Buffering off send to the client as soon as the data is received from Plex.
proxy_redirect off;
proxy_buffering off;
'';
locations."/" = {
proxyWebsockets = true;
proxyPass = "http://plex2.hades:32400/";
};
};
"fedi.xirion.net" = {
enableACME = true;
forceSSL = true;
root = "${pkgs.v.glitch-soc}/public/";
locations = {
"/".tryFiles = "$uri @proxy";
# location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
# add_header Cache-Control "public, max-age=31536000, immutable";
# add_header Strict-Transport-Security "max-age=31536000";
# try_files $uri @proxy;
# }
# location /sw.js {
# add_header Cache-Control "public, max-age=0";
# add_header Strict-Transport-Security "max-age=31536000";
# try_files $uri @proxy;
# }
"@proxy" = {
proxyPass = "http://192.168.0.138:55001";
proxyWebsockets = true;
};
"/api/v1/streaming" = {
proxyPass = "http://192.168.0.138:55000";
proxyWebsockets = true;
};
};
};
"fedi-media.xirion.net" = proxy "http://garage.hades:3902";
};
};
}

View file

@ -0,0 +1,2 @@
# Overseerr & co.
This LXC container hosts all my *arr services and overseerr

View file

@ -0,0 +1,30 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ ... }: {
imports = [
./radarr.nix
./sonarr.nix
./lidarr.nix
./prowlarr.nix
./unpackerr.nix
./overseerr.nix
];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "22.11"; # Did you read the comment?
fileSystems."/mnt/storage" = {
device = "storage:/mnt/storage";
fsType = "nfs";
};
virtualisation.podman.enable = true;
virtualisation.oci-containers.backend = "podman";
}

View file

@ -0,0 +1,31 @@
{ config, ... }:
let vs = config.vault-secrets.secrets;
in {
networking.firewall.allowedTCPPorts = [ 8686 ];
vault-secrets.secrets.lidarr = {
quoteEnvironmentValues = false; # Needed for docker
services = [ "podman-lidarr" ];
};
virtualisation.oci-containers.containers.lidarr = {
image = "randomninjaatk/lidarr-extended:latest";
extraOptions = [ "--pull=newer" ];
environment = {
TZ = "Europe/Amsterdam";
dlClientSource = "deezer";
enableVideoScript = "false";
};
environmentFiles = [
# This file defines arlToken
"${vs.lidarr}/environment"
];
ports = [ "8686:8686" ];
volumes = [
"/var/lib/lidarr/config:/config"
"/var/lib/lidarr/downloads:/downloads-lidarr-extended"
"/mnt/storage/plex/Music:/music"
"/mnt/storage/plex/MusicVideos:/music-videos"
];
};
}

View file

@ -0,0 +1,10 @@
_: {
networking.firewall.allowedTCPPorts = [ 5055 ];
# TODO: Write NixOS package https://github.com/NixOS/nixpkgs/issues/135885
virtualisation.oci-containers.containers.overseerr = {
image = "ghcr.io/sct/overseerr:1.33.2";
environment = { TZ = "Europe/Amsterdam"; };
ports = [ "5055:5055" ];
volumes = [ "/var/lib/overseerr/config:/app/config" ];
};
}

View file

@ -0,0 +1,11 @@
_: {
services.prowlarr = {
enable = true;
openFirewall = true;
};
virtualisation.oci-containers.containers.flaresolverr = {
image = "flaresolverr/flaresolverr:v3.3.10";
ports = [ "8191:8191" ];
};
}

View file

@ -0,0 +1,7 @@
_: {
services.radarr = {
enable = true;
openFirewall = true;
dataDir = "/var/lib/radarr";
};
}

View file

@ -0,0 +1,7 @@
_: {
services.sonarr = {
enable = true;
dataDir = "/var/lib/sonarr";
openFirewall = true;
};
}

View file

@ -0,0 +1,19 @@
{ config, ... }:
let vs = config.vault-secrets.secrets;
in {
vault-secrets.secrets.unpackerr = { };
services.unpackerr = {
enable = true;
debug = false;
environmentFile = "${vs.unpackerr}/environment";
sonarr = {
url = "http://localhost:8989/";
paths = "/mnt/storage/torrents/r/TV";
};
radarr = {
url = "http://localhost:7878/";
paths = "/mnt/storage/torrents/r/Movie";
};
};
}

View file

@ -0,0 +1,31 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, ... }:
{
imports = [ ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.11"; # Did you read the comment?
# Additional packages
environment.systemPackages = with pkgs; [ ];
services.plex = {
enable = true;
package = pkgs.plex-plexpass;
openFirewall = true;
};
fileSystems."/mnt/storage" = {
device = "storage:/mnt/storage";
fsType = "nfs";
};
}

View file

@ -0,0 +1,3 @@
templates:
collections:

Some files were not shown because too many files have changed in this diff Show more