Sync
This commit is contained in:
parent
c1025627ae
commit
cef3a949fe
40 changed files with 3401 additions and 158 deletions
81
flake.lock
generated
Normal file
81
flake.lock
generated
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1730785428,
|
||||
"narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"utils": "utils"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722363685,
|
||||
"narHash": "sha256-XCf2PIAT6lH7BwytgioPmVf/wkzXjSKScC4KzcZgb64=",
|
||||
"owner": "gytis-ivaskevicius",
|
||||
"repo": "flake-utils-plus",
|
||||
"rev": "6b10f51ff73a66bb29f3bc8151a59d217713f496",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "gytis-ivaskevicius",
|
||||
"repo": "flake-utils-plus",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
50
flake.nix
Normal file
50
flake.nix
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
description = "Homelab configuration using flakes";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
utils = {
|
||||
url = "github:gytis-ivaskevicius/flake-utils-plus";
|
||||
inputs.flake-utils.follows = "flake-utils";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = inputs@{
|
||||
self, nixpkgs,
|
||||
flake-utils, utils,
|
||||
...
|
||||
}:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
in
|
||||
utils.lib.mkFlake {
|
||||
inherit self inputs;
|
||||
|
||||
hostDefaults = {
|
||||
inherit system;
|
||||
|
||||
modules = [
|
||||
./modules
|
||||
./users
|
||||
];
|
||||
};
|
||||
|
||||
hosts = {
|
||||
Niko.modules = [ ./hosts/Niko ];
|
||||
|
||||
Ingress.modules = [ ./hosts/Ingress ];
|
||||
Gitea.modules = [ ./hosts/Gitea ];
|
||||
Vaultwarden.modules = [ ./hosts/Vaultwarden ];
|
||||
|
||||
Binnenpost.modules = [ ./hosts/Binnenpost ];
|
||||
ProductionGPU.modules = [ ./hosts/ProductionGPU ];
|
||||
ACE.modules = [ ./hosts/ACE ];
|
||||
|
||||
Template.modules = [ ./hosts/Template ];
|
||||
Development.modules = [ ./hosts/Development ];
|
||||
Testing.modules = [ ./hosts/Testing ];
|
||||
};
|
||||
};
|
||||
}
|
||||
41
hosts/ACE/default.nix
Normal file
41
hosts/ACE/default.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab = {
|
||||
services.actions.enable = true;
|
||||
virtualisation.guest.enable = true;
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostName = "ACE";
|
||||
hostId = "aaaa4100";
|
||||
domain = "depeuter.dev";
|
||||
|
||||
useDHCP = false;
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.41";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
};
|
||||
}
|
||||
81
hosts/Binnenpost/default.nix
Normal file
81
hosts/Binnenpost/default.nix
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
environment = {
|
||||
etc."nixos/tailscale-authkey".text = ''
|
||||
tskey-auth-k1tfJLTnGB11CNTRL-HhnegtfNzQ3G8h71SC2DR38PFXwseQiu
|
||||
'';
|
||||
|
||||
systemPackages = with pkgs; [
|
||||
ethtool
|
||||
];
|
||||
};
|
||||
|
||||
homelab = {
|
||||
apps = {
|
||||
speedtest.enable = true;
|
||||
technitiumDNS.enable = true;
|
||||
};
|
||||
virtualisation.guest.enable = true;
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostName = "Binnenpost";
|
||||
hostId = "aaaa1001";
|
||||
domain = "depeuter.dev";
|
||||
|
||||
useDHCP = false;
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
|
||||
# Open ports in the firewall.
|
||||
firewall = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.89";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
services = {
|
||||
networkd-dispatcher = {
|
||||
enable = true;
|
||||
rules."50-tailscale" = {
|
||||
onState = ["routable"];
|
||||
script = ''
|
||||
${pkgs.ethtool}/bin/ethtool -K ens18 rx-udp-gro-forwarding on rx-gro-list off
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "server";
|
||||
authKeyFile = "/etc/nixos/tailscale-authkey";
|
||||
extraUpFlags = [
|
||||
"--advertise-routes=192.168.0.0/24"
|
||||
"--exit-node"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
};
|
||||
}
|
||||
65
hosts/Development/default.nix
Normal file
65
hosts/Development/default.nix
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
{ config, pkgs, lib, system, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab = {
|
||||
apps.arr = {
|
||||
qbittorrent.enable = true;
|
||||
};
|
||||
virtualisation.guest.enable = true;
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostId = "aaaa9100";
|
||||
domain = "roxanne.depeuter.dev";
|
||||
|
||||
useDHCP = false;
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
|
||||
# Open ports in the firewall.
|
||||
firewall = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.91";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
|
||||
virtualisation.oci-containers.containers = {
|
||||
pgadmin = {
|
||||
image = "dpage/pgadmin4:8.11.0";
|
||||
ports = [
|
||||
"30056:80/tcp"
|
||||
];
|
||||
environment = {
|
||||
# NOTE Required
|
||||
# The email address used when setting up the initial administrator account to login to pgAdmin.
|
||||
PGADMIN_DEFAULT_EMAIL = "kmtl.hugo+pgadmin@gmail.com";
|
||||
# NOTE Required
|
||||
# The password used when setting up the initial administrator account to login to pgAdmin.
|
||||
PGADMIN_DEFAULT_PASSWORD = "ChangeMe";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
38
hosts/Gitea/default.nix
Normal file
38
hosts/Gitea/default.nix
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{ config, pkgs, lib, system, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab = {
|
||||
apps.gitea.enable = true;
|
||||
virtualisation.guest.enable = true;
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostId = "aaaa1500";
|
||||
domain = "depeuter.dev";
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
useDHCP = false;
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.24";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
};
|
||||
}
|
||||
233
hosts/Ingress/default.nix
Normal file
233
hosts/Ingress/default.nix
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
{ config, pkgs, modulesPath, lib, system, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab.virtualisation.guest.enable = true;
|
||||
|
||||
networking = {
|
||||
hostName = "Ingress";
|
||||
hostId = "aaaa1000";
|
||||
domain = "depeuter.dev";
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
useDHCP = false;
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.10";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [
|
||||
80 # HTTP
|
||||
443 # HTTPS
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults = {
|
||||
inherit (config.services.nginx) group;
|
||||
dnsPropagationCheck = true;
|
||||
dnsProvider = "cloudflare";
|
||||
dnsResolver = "1.1.1.1:53";
|
||||
email = "tibo.depeuter@telenet.be";
|
||||
credentialFiles = {
|
||||
CLOUDFLARE_DNS_API_TOKEN_FILE = "/var/lib/secrets/depeuter-dev-cloudflare-api-token";
|
||||
};
|
||||
reloadServices = [ "nginx" ];
|
||||
};
|
||||
certs = {
|
||||
"depeuter.dev" = {
|
||||
domain = "depeuter.dev";
|
||||
extraDomainNames = [ "*.depeuter.dev" ];
|
||||
};
|
||||
"cloud.depeuter.dev" = { };
|
||||
"git.depeuter.dev" = { };
|
||||
"jelly.depeuter.dev" = { };
|
||||
"vault.depeuter.dev" = { };
|
||||
};
|
||||
};
|
||||
|
||||
# List services that you want to enable.
|
||||
services = {
|
||||
# Enable Nginx as a reverse proxy
|
||||
nginx = {
|
||||
enable = true;
|
||||
|
||||
# Use recommended settings
|
||||
# recommendedGzipSettings = true;
|
||||
# recommendedOptimisation = true;
|
||||
# recommendedProxySettings = true;
|
||||
# recommendedTlsSettings = true;
|
||||
|
||||
# Only allow PFS-enabled ciphers with AES256
|
||||
sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
|
||||
|
||||
upstreams.docservice.servers."192.168.0.14:8080" = {};
|
||||
|
||||
appendHttpConfig = ''
|
||||
map $http_x_forwarded_proto $the_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
"" $scheme;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_host $the_host {
|
||||
default $http_x_forwarded_host;
|
||||
"" $host;
|
||||
}
|
||||
|
||||
map $http_upgrade $proxy_connection {
|
||||
default upgrade;
|
||||
"" close;
|
||||
}
|
||||
'';
|
||||
|
||||
# Define hosts
|
||||
virtualHosts = {
|
||||
# Disable automatic routing.
|
||||
"default" = {
|
||||
locations."/".return = "301 https://youtu.be/dQw4w9WgXcQ";
|
||||
default = true;
|
||||
};
|
||||
|
||||
"cloud.depeuter.dev" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://192.168.0.14";
|
||||
extraConfig = ''
|
||||
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||
fastcgi_request_buffering off;
|
||||
'';
|
||||
};
|
||||
"/office/" = {
|
||||
proxyPass = "http://192.168.0.14:8080/";
|
||||
priority = 500;
|
||||
recommendedProxySettings = false;
|
||||
extraConfig = ''
|
||||
proxy_http_version 1.1;
|
||||
'';
|
||||
};
|
||||
};
|
||||
extraConfig = ''
|
||||
client_max_body_size 10G;
|
||||
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $proxy_connection;
|
||||
proxy_set_header X-Forwarded-Host $the_host/office;
|
||||
proxy_set_header X-Forwarded-Proto $the_scheme;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
'';
|
||||
};
|
||||
"calendar.depeuter.dev".locations."/".return = "301 https://cloud.depeuter.dev/apps/calendar";
|
||||
"tasks.depeuter.dev".locations."/".return = "301 https://cloud.depeuter.dev/apps/tasks";
|
||||
"notes.depeuter.dev".locations."/".return = "301 https://cloud.depeuter.dev/apps/notes";
|
||||
|
||||
"jelly.depeuter.dev" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://192.168.0.94:8096";
|
||||
extraConfig = ''
|
||||
# Proxy main Jellyfin traffic
|
||||
proxy_set_header Host $host;
|
||||
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 X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
|
||||
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
"/socket" = {
|
||||
proxyPass = "http://192.168.0.91:8096";
|
||||
extraConfig = ''
|
||||
# Proxy Jellyfin Websockets traffic
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
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 X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
'';
|
||||
};
|
||||
};
|
||||
extraConfig = ''
|
||||
client_max_body_size 20M;
|
||||
|
||||
# Security / XSS Mitigation Headers
|
||||
# NOTE: X-Frame-Options may cause issues with the webOS app
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-Content-Type-Options "nosniff";
|
||||
|
||||
# Permissions policy. May cause issues with some clients
|
||||
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
|
||||
|
||||
# Content Security Policy
|
||||
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
||||
# Enforces https content and restricts JS/CSS to origin
|
||||
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
|
||||
# NOTE: The default CSP headers may cause issues with the webOS app
|
||||
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'";
|
||||
'';
|
||||
};
|
||||
"git.depeuter.dev" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".proxyPass = "http://192.168.0.24:3000";
|
||||
extraConfig = ''
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Host $host;
|
||||
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;
|
||||
|
||||
client_max_body_size 512M;
|
||||
keepalive_timeout 600s;
|
||||
proxy_buffers 4 256k; # Number and size of buffers for reading response
|
||||
proxy_buffer_size 256k; # Buffer for the first part of the response
|
||||
proxy_busy_buffers_size 256k; # Max size of busy buffers
|
||||
proxy_http_version 1.1;
|
||||
proxy_read_timeout 600s;
|
||||
proxy_temp_file_write_size 256k; # Size of temp file for large responses
|
||||
'';
|
||||
};
|
||||
"vault.depeuter.dev" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/".proxyPass = "http://192.168.0.22:10102";
|
||||
"~ ^/admin".return = 403;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
};
|
||||
}
|
||||
32
hosts/Isabel/dashboard/config/bookmarks.yaml
Normal file
32
hosts/Isabel/dashboard/config/bookmarks.yaml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
- Office:
|
||||
- Zoho Mail:
|
||||
- icon: zohomail
|
||||
href: https://mail.zoho.eu
|
||||
- Network:
|
||||
- Cloudlfare:
|
||||
- icon: cloudflare
|
||||
href: https://dash.cloudflare.com
|
||||
- Pulsetic:
|
||||
- href: https://status.depeuter.dev
|
||||
icon: https://pulsetic.com/favicon-196x196.png
|
||||
- Telenet Internet usage:
|
||||
- icon: https://static.telenet.be/assets/favicon/favicon.ico
|
||||
href: https://www2.telenet.be/nl/klantenservice/raadpleeg-je-internetverbruik/
|
||||
- Telenet Modem:
|
||||
- icon: https://static.telenet.be/assets/favicon/favicon.ico
|
||||
# href: https://mijn.telenet.be/mijntelenet/rgw/settings.do?identifier=u381160&action=showAdvancedSettings
|
||||
href: https://www2.telenet.be/residential/nl/mijn-telenet/je-thuisnetwerk#/mainnavitem=hgw/mainnavitemid=item-1/subnavitem=modem_general
|
||||
- TransIP:
|
||||
- icon: https://www.transip.eu/cache-60c9b25f/img/transip-new/favicons/favicon.png
|
||||
href: https://www.transip.eu/cp/
|
||||
- Homemade:
|
||||
- AI-Transparency:
|
||||
- href: https://ai-transparency.depeuter.dev
|
||||
icon: https://ai-transparency.depeuter.dev/img/transparency.png
|
||||
- Down-message:
|
||||
- href: https://down.depeuter.dev
|
||||
icon: https://down.depeuter.dev/assets/icon.jpg
|
||||
- Portfolio:
|
||||
- href: https://tibo.depeuter.dev
|
||||
icon: https://tibo.depeuter.dev/assets/owl_circuit.png
|
||||
|
||||
30
hosts/Isabel/dashboard/config/services.yaml
Normal file
30
hosts/Isabel/dashboard/config/services.yaml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
- Networking:
|
||||
- AXE5400 Tri-Band Wi-Fi 6E Router:
|
||||
description: Router
|
||||
href: https://tplinkwifi.net
|
||||
ping: http://192.168.0.1
|
||||
icon: tp-link
|
||||
- Traefik Isabel:
|
||||
description: Reverse proxy manager
|
||||
href: https://traefik.isabel.depeuter.dev/dashboard/#
|
||||
ping: https://traefik.isabel.depeuter.dev/dashboard/#
|
||||
icon: traefik
|
||||
widget:
|
||||
type: traefik
|
||||
url: https://traefik.isabel.depeuter.dev
|
||||
- Traefik Niko:
|
||||
description: Reverse proxy manager
|
||||
href: https://traefik.niko.depeuter.dev/dashboard/#
|
||||
ping: https://traefik.niko.depeuter.dev/dashboard/#
|
||||
- Technitium DNS Isabel:
|
||||
description: DNS server
|
||||
href: https://dns.Isabel.depeuter.dev
|
||||
ping: http://192.168.0.13:53
|
||||
icon: technitium
|
||||
- Technitium DNS Niko:
|
||||
description: DNS server
|
||||
href: https://dns.niko.depeuter.dev
|
||||
ping: http://192.168.0.30:53
|
||||
icon: technitium
|
||||
|
||||
|
||||
255
hosts/Isabel/default.nix
Normal file
255
hosts/Isabel/default.nix
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
# Include the results of the hardware scan.
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
# Use the systemd-boot EFI boot loader.
|
||||
boot.loader = {
|
||||
systemd-boot.enable = true;
|
||||
efi = {
|
||||
canTouchEfiVariables = true;
|
||||
efiSysMountPoint = "/boot/efi";
|
||||
};
|
||||
};
|
||||
|
||||
console = {
|
||||
font = "Lat2-Terminus16";
|
||||
keyMap = "us";
|
||||
};
|
||||
|
||||
# List packages installed in the system profile. To search, run:
|
||||
# $ nix search wget
|
||||
environment.systemPackages = with pkgs; [
|
||||
];
|
||||
|
||||
environment.etc = {
|
||||
"homepage/bookmarks.yaml".text = ''
|
||||
- Office:
|
||||
- Zoho Mail:
|
||||
- icon: zohomail
|
||||
href: https://mail.zoho.eu
|
||||
- Network:
|
||||
- Cloudlfare:
|
||||
- icon: cloudflare
|
||||
href: https://dash.cloudflare.com
|
||||
- TransIP:
|
||||
- icon: https://www.transip.eu/cache-60c9b25f/img/transip-new/favicons/favicon.png
|
||||
href: https://www.transip.eu/cp/
|
||||
- Telenet Internet usage:
|
||||
- icon: https://static.telenet.be/assets/favicon/favicon.ico
|
||||
href: https://www2.telenet.be/nl/klantenservice/raadpleeg-je-internetverbruik/
|
||||
- Telenet Modem:
|
||||
- icon: https://static.telenet.be/assets/favicon/favicon.ico
|
||||
# href: https://mijn.telenet.be/mijntelenet/rgw/settings.do?identifier=u381160&action=showAdvancedSettings
|
||||
href: https://www2.telenet.be/residential/nl/mijn-telenet/je-thuisnetwerk#/mainnavitem=hgw/mainnavitemid=item-1/subnavitem=modem_general
|
||||
- Pulsetic:
|
||||
- href: https://status.depeuter.dev
|
||||
icon: https://pulsetic.com/favicon-196x196.png
|
||||
- Homemade:
|
||||
- AI-Transparency:
|
||||
- href: https://ai-transparency.depeuter.dev
|
||||
icon: https://ai-transparency.depeuter.dev/img/transparency.png
|
||||
- Down-message:
|
||||
- href: https://down.depeuter.dev
|
||||
icon: https://down.depeuter.dev/assets/icon.jpg
|
||||
- Portfolio:
|
||||
- href: https://tibo.depeuter.dev
|
||||
icon: https://tibo.depeuter.dev/assets/owl_circuit.png
|
||||
'';
|
||||
|
||||
"homepage/services.yaml".text = ''
|
||||
- Networking:
|
||||
- Traefik Isabel:
|
||||
description: Reverse proxy manager
|
||||
href: https://traefik.isabel.depeuter.dev/dashboard/#
|
||||
ping: https://traefik.isabel.depeuter.dev/dashboard/#
|
||||
icon: traefik
|
||||
widget:
|
||||
type: traefik
|
||||
url: https://traefik.isabel.depeuter.dev
|
||||
- Traefik Niko:
|
||||
description: Reverse proxy manager
|
||||
href: https://traefik.niko.depeuter.dev/dashboard/#
|
||||
ping: https://traefik.niko.depeuter.dev/dashboard/#
|
||||
icon: traefik
|
||||
widget:
|
||||
type: traefik
|
||||
url: https://traefik.niko.depeuter.dev
|
||||
'';
|
||||
|
||||
"homepage/settings.yaml".text = ''
|
||||
---
|
||||
# For configuration options and examples, please see:
|
||||
# https://gethomepage.dev/en/configs/settings
|
||||
|
||||
providers:
|
||||
openweathermap: openweathermapapikey
|
||||
weatherapi: weatherapiapikey
|
||||
'';
|
||||
};
|
||||
|
||||
homelab.apps.technitiumDNS.enable = true;
|
||||
|
||||
# Select internationalisation properties.
|
||||
i18n.defaultLocale = "en_GB.utf8";
|
||||
|
||||
networking = {
|
||||
hostName = "Hugo-Isabel";
|
||||
domain = "depeuter.dev";
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
# Open ports in the firewall.
|
||||
firewall = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
networkmanager.enable = true;
|
||||
};
|
||||
|
||||
# List services that you want to enable:
|
||||
services = {
|
||||
tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "server";
|
||||
authKeyFile = "/etc/nixos/tailscale-authkey";
|
||||
extraUpFlags = [
|
||||
"--advertise-routes=192.168.0.0/24"
|
||||
"--exit-node"
|
||||
];
|
||||
};
|
||||
|
||||
# Fix DNS issues. See:
|
||||
# https://github.com/tailscale/tailscale/issues/4254
|
||||
# resolved.enable = true;
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
virtualisation = {
|
||||
docker = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
};
|
||||
|
||||
oci-containers = {
|
||||
backend = "docker";
|
||||
containers = {
|
||||
reverse-proxy = {
|
||||
hostname = "traefik";
|
||||
image = "traefik:v3.0";
|
||||
cmd = [
|
||||
"--api.insecure=true"
|
||||
# Add Docker provider
|
||||
"--providers.docker=true"
|
||||
"--providers.docker.exposedByDefault=false"
|
||||
# Add web entrypoint
|
||||
"--entrypoints.web.address=:80/tcp"
|
||||
"--entrypoints.web.http.redirections.entrypoint.to=websecure"
|
||||
"--entrypoints.web.http.redirections.entrypoint.scheme=https"
|
||||
# Add websecure entrypoint
|
||||
"--entrypoints.websecure.address=:443/tcp"
|
||||
"--entrypoints.websecure.http.tls=true"
|
||||
"--entrypoints.websecure.http.tls.certResolver=letsencrypt"
|
||||
"--entrypoints.websecure.http.tls.domains[0].main=depeuter.dev"
|
||||
"--entrypoints.websecure.http.tls.domains[0].sans=*.depeuter.dev"
|
||||
"--entrypoints.websecure.http.tls.domains[1].sans=*.isabel.depeuter.dev"
|
||||
"--entrypoints.websecure.http.tls.domains[2].sans=*.jelly.depeuter.dev"
|
||||
# Certificates
|
||||
"--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
|
||||
"--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
|
||||
"--certificatesresolvers.letsencrypt.acme.email=tibo.depeuter@telenet.be"
|
||||
"--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
|
||||
|
||||
# Additional routes
|
||||
];
|
||||
ports = [
|
||||
"80:80/tcp"
|
||||
"443:443/tcp"
|
||||
# "8080:8080/tcp" # The Web UI (enabled by --api.insecure=true)
|
||||
];
|
||||
environment = {
|
||||
# TODO Hide this!
|
||||
"CLOUDFLARE_DNS_API_TOKEN" = "6Vz64Op_a6Ls1ljGeBxFoOVfQ-yB-svRbf6OyPv2";
|
||||
};
|
||||
environmentFiles = [
|
||||
];
|
||||
volumes = [
|
||||
"/var/run/docker.sock:/var/run/docker.sock:ro" # So that Traefik can listen to the Docker events
|
||||
"letsencrypt:/letsencrypt"
|
||||
];
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.traefik.rule" = "Host(`traefik.isabel.depeuter.dev`)";
|
||||
"traefik.http.services.traefik.loadbalancer.server.port" = "8080";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
feishin = {
|
||||
hostname = "feishin";
|
||||
image = "ghcr.io/jeffvli/feishin:0.7.1";
|
||||
ports = [
|
||||
# "9180:9180/tcp" # Web player (HTTP)
|
||||
];
|
||||
environment = {
|
||||
# pre defined server name
|
||||
SERVER_NAME = "Hugo";
|
||||
# When true AND name/type/url are set, only username/password can be toggled
|
||||
SERVER_LOCK = "true";
|
||||
# navidrome also works
|
||||
SERVER_TYPE = "jellyfin";
|
||||
# http://address:port
|
||||
SERVER_URL= "https://jelly.depeuter.dev";
|
||||
TZ = config.time.timeZone;
|
||||
};
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.feishin.rule" = "Host(`music.depeuter.dev`)";
|
||||
"traefik.http.services.feishin.loadbalancer.server.port" = "9180";
|
||||
"traefik.tls.options.default.minVersion" = "VersionTLS13";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
dashboard = {
|
||||
hostname = "dashboard";
|
||||
image = "ghcr.io/gethomepage/homepage:v0.9.3";
|
||||
ports = [
|
||||
# "3000:3000/tcp"
|
||||
];
|
||||
volumes = [
|
||||
"/etc/homepage:/app/config" # Make sure your local config directory exists
|
||||
"/var/run/docker.sock:/var/run/docker.sock:ro" # optional, for docker integrations
|
||||
];
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.dashboard.rule" = "Host(`dash.depeuter.dev`)";
|
||||
"traefik.http.services.dashboard.loadbalancer.server.port" = "3000";
|
||||
"traefik.tls.options.default.minVersion" = "VersionTLS13";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
prometheus = {
|
||||
hostname = "prometheus";
|
||||
image = "prom/prometheus:v2.45.6";
|
||||
ports = [
|
||||
# "127.0.0.1:9090:9090/tcp"
|
||||
];
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.prometheus.rule" = "Host(`prometheus.isabel.depeuter.dev`)";
|
||||
"traefik.http.services.prometheus.loadbalancer.server.port" = "9090";
|
||||
"traefik.tls.options.default.minVersion" = "VersionTLS13";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
39
hosts/Isabel/hardware-configuration.nix
Normal file
39
hosts/Isabel/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# 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.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "xhci_pci" "ahci" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-label/NIX-ROOT";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot/efi" =
|
||||
{ device = "/dev/disk/by-label/NIX-BOOT";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-label/SWAP"; }
|
||||
];
|
||||
|
||||
# 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.ens3.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
|
|
@ -6,6 +6,11 @@
|
|||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
homelab = {
|
||||
apps.technitiumDNS.enable = true;
|
||||
users.deploy.enable = true;
|
||||
};
|
||||
|
||||
# Use the systemd-boot EFI boot loader.
|
||||
boot.loader = {
|
||||
systemd-boot.enable = true;
|
||||
|
|
@ -23,11 +28,7 @@
|
|||
# List packages installed in the system profile. To search, run:
|
||||
# $ nix search wget
|
||||
environment.systemPackages = with pkgs; [
|
||||
curl
|
||||
git
|
||||
tmux
|
||||
vim
|
||||
wget
|
||||
cifs-utils
|
||||
];
|
||||
|
||||
hardware = {
|
||||
|
|
@ -58,16 +59,6 @@
|
|||
'';
|
||||
};
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixFlakes;
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
settings.trusted-users = [
|
||||
config.users.users.admin.name
|
||||
];
|
||||
};
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
# List services that you want to enable:
|
||||
|
|
@ -88,15 +79,6 @@
|
|||
user = config.users.users.jellyfin-mpv-shim.name;
|
||||
};
|
||||
|
||||
openssh = {
|
||||
# Enable the OpenSSH daemon.
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
};
|
||||
};
|
||||
|
||||
tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "server";
|
||||
|
|
@ -114,32 +96,8 @@
|
|||
|
||||
sound.enable = true;
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "Europe/Brussels";
|
||||
|
||||
users = {
|
||||
# Define users groups
|
||||
groups = {
|
||||
# The group used to deploy rebuilds without password authentication
|
||||
deploy = { };
|
||||
};
|
||||
|
||||
# Define a user account. Don't forget to set a password with 'passwd'.
|
||||
users = {
|
||||
admin = {
|
||||
description = "System Administrator";
|
||||
isNormalUser = true;
|
||||
extraGroups = [
|
||||
config.users.groups.wheel.name # Enable 'sudo' for the user.
|
||||
config.users.groups.deploy.name
|
||||
];
|
||||
initialPassword = "ChangeMe";
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPrG+ldRBdCeHEXrsy/qHXIJYg8xQXVuiUR0DxhFjYNg"
|
||||
];
|
||||
};
|
||||
|
||||
jellyfin-mpv-shim = {
|
||||
users.users.jellyfin-mpv-shim = {
|
||||
description = "Jellyfin MPV Shim User";
|
||||
isNormalUser = true;
|
||||
extraGroups = [
|
||||
|
|
@ -152,35 +110,6 @@
|
|||
socat
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
extraRules = [
|
||||
{
|
||||
groups = [ config.users.groups.deploy.name ];
|
||||
commands = [
|
||||
{
|
||||
command = "/nix/store/*/bin/switch-to-configuration";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
{
|
||||
command = "/run/current-system/sw/bin/nix-store";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
{
|
||||
command = ''/bin/sh -c "readlink -e /nix/var/nix/profiles/system || readlink -e /run/current-system"'';
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
{
|
||||
command = "${config.system.build.nixos-rebuild}/bin/nixos-rebuild";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services."cage-tty1".serviceConfig.Restart = "always";
|
||||
|
||||
|
|
@ -229,6 +158,7 @@
|
|||
# "8080:8080/tcp" # The Web UI (enabled by --api.insecure=true)
|
||||
];
|
||||
environment = {
|
||||
# TODO Hide this!
|
||||
"CLOUDFLARE_DNS_API_TOKEN" = "6Vz64Op_a6Ls1ljGeBxFoOVfQ-yB-svRbf6OyPv2";
|
||||
};
|
||||
environmentFiles = [
|
||||
|
|
@ -244,67 +174,6 @@
|
|||
};
|
||||
autoStart = true;
|
||||
};
|
||||
technitium-dns = {
|
||||
hostname = "technitium-dns";
|
||||
image = "technitium/dns-server:12.1";
|
||||
ports = [
|
||||
# "5380:5380/tcp" #DNS web console (HTTP)
|
||||
# "53443:53443/tcp" #DNS web console (HTTPS)
|
||||
"53:53/udp" #DNS service
|
||||
"53:53/tcp" #DNS service
|
||||
# "853:853/udp" #DNS-over-QUIC service
|
||||
# "853:853/tcp" #DNS-over-TLS service
|
||||
# "443:443/udp" #DNS-over-HTTPS service (HTTP/3)
|
||||
# "443:443/tcp" #DNS-over-HTTPS service (HTTP/1.1, HTTP/2)
|
||||
# "80:80/tcp" #DNS-over-HTTP service (use with reverse proxy or certbot certificate renewal)
|
||||
# "8053:8053/tcp" #DNS-over-HTTP service (use with reverse proxy)
|
||||
# "67:67/udp" #DHCP service
|
||||
];
|
||||
environment = {
|
||||
# The primary domain name used by this DNS Server to identify itself.
|
||||
DNS_SERVER_DOMAIN = config.networking.hostName;
|
||||
# DNS Server will use IPv6 for querying whenever possible with this option enabled.
|
||||
DNS_SERVER_PREFER_IPV6 = "true";
|
||||
# The TCP port number for the DNS web console over HTTP protocol.
|
||||
# DNS_SERVER_WEB_SERVICE_HTTP_PORT=5380
|
||||
# The TCP port number for the DNS web console over HTTPS protocol.
|
||||
# DNS_SERVER_WEB_SERVICE_HTTPS_PORT=53443
|
||||
# Enables HTTPS for the DNS web console.
|
||||
# DNS_SERVER_WEB_SERVICE_ENABLE_HTTPS=false
|
||||
# Enables self signed TLS certificate for the DNS web console.
|
||||
# DNS_SERVER_WEB_SERVICE_USE_SELF_SIGNED_CERT=false
|
||||
# Enables DNS server optional protocol DNS-over-HTTP on TCP port 8053 to be used with a TLS terminating reverse proxy like nginx.
|
||||
# DNS_SERVER_OPTIONAL_PROTOCOL_DNS_OVER_HTTP=false
|
||||
# Recursion options: Allow, Deny, AllowOnlyForPrivateNetworks, UseSpecifiedNetworks.
|
||||
#nDNS_SERVER_RECURSION=AllowOnlyForPrivateNetworks
|
||||
# Comma separated list of IP addresses or network addresses to deny recursion. Valid only for `UseSpecifiedNetworks` recursion option.
|
||||
# DNS_SERVER_RECURSION_DENIED_NETWORKS=1.1.1.0/24
|
||||
# Comma separated list of IP addresses or network addresses to allow recursion. Valid only for `UseSpecifiedNetworks` recursion option.
|
||||
# DNS_SERVER_RECURSION_ALLOWED_NETWORKS=127.0.0.1, 192.168.1.0/24
|
||||
# Sets the DNS server to block domain names using Blocked Zone and Block List Zone.
|
||||
DNS_SERVER_ENABLE_BLOCKING = "false";
|
||||
# Specifies if the DNS Server should respond with TXT records containing a blocked domain report for TXT type requests.
|
||||
# DNS_SERVER_ALLOW_TXT_BLOCKING_REPORT=false
|
||||
# A comma separated list of block list URLs.
|
||||
# DNS_SERVER_BLOCK_LIST_URLS=
|
||||
#Comma separated list of forwarder addresses.
|
||||
DNS_SERVER_FORWARDERS="195.130.130.2,195.130.131.2";
|
||||
# Forwarder protocol options: Udp, Tcp, Tls, Https, HttpsJson.
|
||||
# DNS_SERVER_FORWARDER_PROTOCOL=Tcp
|
||||
# Enable this option to use local time instead of UTC for logging.
|
||||
# DNS_SERVER_LOG_USING_LOCAL_TIME=true
|
||||
};
|
||||
volumes = [
|
||||
"dns:/etc/dns"
|
||||
];
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.technitium-dns.rule" = "Host(`dns.niko.depeuter.dev`)";
|
||||
"traefik.http.services.technitium-dns.loadbalancer.server.port" = "5380";
|
||||
"traefik.tls.options.default.minVersion" = "VersionTLS13";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@
|
|||
fsType = "vfat";
|
||||
};
|
||||
|
||||
# "/data/photos" = {
|
||||
# device = "//192.168.0.11/CANVAS";
|
||||
# fsType = "cifs";
|
||||
# options = let
|
||||
# # this line prevents hanging on network split
|
||||
# automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
|
||||
# in ["${automount_opts},credentials=/etc/nixos/smb-secrets"];
|
||||
# };
|
||||
"/media/photos" = {
|
||||
device = "//192.168.0.11/CANVAS";
|
||||
fsType = "cifs";
|
||||
options = let
|
||||
# This line prevents hanging on network split
|
||||
automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s,user,users";
|
||||
in ["${automount_opts},credentials=/etc/nixos/smb-secrets,uid=1002,gid=100"];
|
||||
};
|
||||
};
|
||||
|
||||
swapDevices = [
|
||||
|
|
|
|||
98
hosts/ProductionGPU/default.nix
Normal file
98
hosts/ProductionGPU/default.nix
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
{ config, pkgs, lib, system, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab = {
|
||||
apps.jellyfin.enable = true;
|
||||
virtualisation.guest.enable = true;
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostId = "aaaa2200";
|
||||
domain = "roxanne.depeuter.dev";
|
||||
|
||||
useDHCP = false;
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "enp6s18";
|
||||
};
|
||||
|
||||
# Open ports in the firewall.
|
||||
firewall = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
interfaces.enp6s18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.94";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "unstable";
|
||||
|
||||
### Nvidia GPU support ###
|
||||
|
||||
services.xserver.videoDrivers = [ "nvidia" ];
|
||||
|
||||
# virtualisation.docker.package = pkgs.nvidia-docker;
|
||||
|
||||
nixpkgs.config = {
|
||||
allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
||||
"nvidia-x11"
|
||||
"nvidia-settings"
|
||||
"nvidia-persistenced"
|
||||
];
|
||||
|
||||
# enable vaapi on OS-level
|
||||
# packageOverrides = pkgs: {
|
||||
# vaapiIntel = pkgs.vaapiIntel.override {
|
||||
# enableHybridCodec = true;
|
||||
# };
|
||||
# };
|
||||
};
|
||||
|
||||
hardware = {
|
||||
opengl = {
|
||||
enable = true;
|
||||
# driSupport = true;
|
||||
# driSupport32Bit = true;
|
||||
extraPackages = with pkgs; [
|
||||
# intel-media-driver
|
||||
# intel-vaapi-driver # previously vaapiIntel
|
||||
# vaapiVdpau
|
||||
# intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
|
||||
# unstable.vpl-gpu-rt # QSV on 11th gen or newer
|
||||
# intel-media-sdk # QSV up to 11th gen
|
||||
];
|
||||
};
|
||||
|
||||
nvidia = {
|
||||
package = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||
# Whether to enable kernel modesetting when using the NVIDIA proprietary driver.
|
||||
modesetting.enable = true;
|
||||
# powerManagement = {
|
||||
# enable = false;
|
||||
# finegrained = false;
|
||||
# };
|
||||
open = false;
|
||||
nvidiaSettings = false;
|
||||
|
||||
# Whether to enable nvidia-persistenced a update for NVIDIA GPU headless mode, i.e. It ensures all GPUs stay awake even during headless mode .
|
||||
# nvidiaPersistenced = true;
|
||||
};
|
||||
nvidia-container-toolkit.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
36
hosts/Template/default.nix
Normal file
36
hosts/Template/default.nix
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{ config, pkgs, lib, system, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab.virtualisation.guest.enable = true;
|
||||
|
||||
networking = {
|
||||
# TODO hostName = "nixos";
|
||||
# TODO hostId = "aaaa9000";
|
||||
domain = "depeuter.dev";
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
useDHCP = false;
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.90";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
};
|
||||
}
|
||||
48
hosts/Testing/default.nix
Normal file
48
hosts/Testing/default.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{ config, pkgs, lib, system, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab = {
|
||||
virtualisation = {
|
||||
containers.enable = true;
|
||||
guest.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostName = "Testing";
|
||||
hostId = "aaaa9200";
|
||||
domain = "roxanne.depeuter.dev";
|
||||
|
||||
useDHCP = false;
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
|
||||
# Open ports in the firewall.
|
||||
firewall = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.92";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
};
|
||||
}
|
||||
38
hosts/Vaultwarden/default.nix
Normal file
38
hosts/Vaultwarden/default.nix
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{ config, pkgs, lib, system, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
homelab = {
|
||||
apps.vaultwarden.enable = true;
|
||||
virtualisation.guest.enable = true;
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostId = "aaaa1300";
|
||||
domain = "depeuter.dev";
|
||||
|
||||
enableIPv6 = true;
|
||||
|
||||
useDHCP = false;
|
||||
defaultGateway = {
|
||||
address = "192.168.0.1";
|
||||
interface = "ens18";
|
||||
};
|
||||
interfaces.ens18 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.0.22";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nameservers = [
|
||||
"1.1.1.1" # Cloudflare
|
||||
"1.0.0.1" # Cloudflare
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
};
|
||||
}
|
||||
269
modules/apps/arr/default.nix
Normal file
269
modules/apps/arr/default.nix
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.arr;
|
||||
|
||||
networkName = "arrStack";
|
||||
appNames = [ "bazarr" "lidarr" "prowlarr" "qbittorrent" "radarr" "sonarr" ];
|
||||
inUse = builtins.any (app: cfg.${app}.enable) appNames;
|
||||
|
||||
PGID = toString config.users.groups.media.gid;
|
||||
UMASK = "002";
|
||||
in {
|
||||
options.homelab.apps.arr = {
|
||||
enable = lib.mkEnableOption "Arr Stack using Docker";
|
||||
|
||||
bazarr.enable = lib.mkEnableOption "Bazarr using Docker";
|
||||
lidarr.enable = lib.mkEnableOption "Lidarr using Docker";
|
||||
prowlarr.enable = lib.mkEnableOption "Prowlarr using Docker";
|
||||
qbittorrent.enable = lib.mkEnableOption "qBittorrent using Docker";
|
||||
radarr.enable = lib.mkEnableOption "Radarr using Docker";
|
||||
sonarr.enable = lib.mkEnableOption "Sonarr using Docker";
|
||||
};
|
||||
|
||||
config = {
|
||||
homelab = {
|
||||
users.media.enable = lib.mkIf inUse true;
|
||||
|
||||
# "Master switch": Enable all apps.
|
||||
apps.arr = {
|
||||
bazarr.enable = lib.mkIf cfg.enable true;
|
||||
lidarr.enable = lib.mkIf cfg.enable true;
|
||||
prowlarr.enable = lib.mkIf cfg.enable true;
|
||||
qbittorrent.enable = lib.mkIf cfg.enable true;
|
||||
radarr.enable = lib.mkIf cfg.enable true;
|
||||
sonarr.enable = lib.mkIf cfg.enable true;
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems = lib.mkIf inUse {
|
||||
"/srv/video" = {
|
||||
device = "192.168.0.11:/mnt/SMALL/MEDIA/VIDEO";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"rw"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft"
|
||||
"timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
|
||||
"nosuid" "tcp"
|
||||
];
|
||||
};
|
||||
|
||||
"/srv/qbittorrent" = {
|
||||
device = "192.168.0.11:/mnt/SMALL/CONFIG/QBITTORRENT/qBittorrent";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"rw"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft"
|
||||
"nosuid" "tcp"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Make sure the Docker network exists.
|
||||
systemd.services."docker-${networkName}-create-network" = lib.mkIf inUse {
|
||||
description = "Create Docker network for ${networkName}";
|
||||
requiredBy = [
|
||||
"docker-bazarr.service"
|
||||
"docker-lidarr.service"
|
||||
"docker-prowlarr.service"
|
||||
"docker-qbittorrent.service"
|
||||
"docker-radarr.service"
|
||||
"docker-sonarr.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
if ! ${pkgs.docker}/bin/docker network ls | grep -q ${networkName}; then
|
||||
${pkgs.docker}/bin/docker network create ${networkName}
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Create a user for each app.
|
||||
users.users = {
|
||||
bazarr = lib.mkIf cfg.bazarr.enable {
|
||||
uid = lib.mkForce 3003;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
lidarr = lib.mkIf cfg.lidarr.enable {
|
||||
uid = lib.mkForce 3002;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
prowlarr = lib.mkIf cfg.prowlarr.enable {
|
||||
uid = lib.mkForce 3004;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
qbittorrent = lib.mkIf cfg.qbittorrent.enable {
|
||||
uid = lib.mkForce 3005;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
radarr = lib.mkIf cfg.radarr.enable {
|
||||
uid = lib.mkForce 3006;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
sonarr = lib.mkIf cfg.sonarr.enable {
|
||||
uid = lib.mkForce 3007;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers = {
|
||||
bazarr = lib.mkIf cfg.bazarr.enable {
|
||||
hostname = "bazarr";
|
||||
image = "ghcr.io/hotio/bazarr:release-1.4.4";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"6767:6767/tcp"
|
||||
"6767:6767/udp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
|
||||
"--mount" ''type=volume,source=bazarr-backup,target=/backup,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/mnt/BIG/BACKUP/BAZARR,"volume-opt=o=addr=192.168.0.11,rw,nfsvers=4.2,async,nosuid"''
|
||||
];
|
||||
environment = {
|
||||
PUID = toString config.users.users.bazarr.uid;
|
||||
inherit PGID UMASK;
|
||||
TZ = config.time.timeZone;
|
||||
WEBUI_PORTS = "6767/tcp,6767/udp";
|
||||
};
|
||||
volumes = [
|
||||
"bazarr-config:/config"
|
||||
"/srv/video:/data"
|
||||
];
|
||||
};
|
||||
|
||||
lidarr = lib.mkIf cfg.lidarr.enable {
|
||||
hostname = "lidarr";
|
||||
image = "ghcr.io/hotio/lidarr:release-2.5.3.4341";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"8686:8686/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
|
||||
"--mount" ''type=volume,source=lidarr-backup,target=/backup,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/mnt/BIG/BACKUP/LIDARR,"volume-opt=o=addr=192.168.0.11,rw,nfsvers=4.2,async,nosuid"''
|
||||
];
|
||||
environment = {
|
||||
PUID = toString config.users.users.lidarr.uid;
|
||||
inherit PGID UMASK;
|
||||
TZ = config.time.timeZone;
|
||||
};
|
||||
volumes = [
|
||||
"lidarr-config:/config"
|
||||
# TODO "data:/data"
|
||||
];
|
||||
};
|
||||
|
||||
prowlarr = lib.mkIf cfg.prowlarr.enable {
|
||||
hostname = "prowlarr";
|
||||
image = "ghcr.io/hotio/prowlarr:release-1.23.1.4708";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"9696:9696/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
environment = {
|
||||
PUID = toString config.users.users.prowlarr.uid;
|
||||
inherit PGID UMASK;
|
||||
TZ = config.time.timeZone;
|
||||
};
|
||||
volumes = [
|
||||
# TODO "config:/config"
|
||||
];
|
||||
};
|
||||
|
||||
qbittorrent = lib.mkIf cfg.qbittorrent.enable {
|
||||
hostname = "qbittorrent";
|
||||
image = "ghcr.io/hotio/qbittorrent:release-4.6.7";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"10095:10095/udp"
|
||||
"10095:10095/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
|
||||
"--mount" ''type=volume,source=torrents,target=/data,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/mnt/SMALL/MEDIA/TORRENT,"volume-opt=o=addr=192.168.0.11,rw,nfsvers=4.2,async,nosuid"''
|
||||
];
|
||||
environment = {
|
||||
PUID = toString config.users.users.qbittorrent.uid;
|
||||
inherit PGID UMASK;
|
||||
TZ = config.time.timeZone;
|
||||
WEBUI_PORTS = "10095/tcp,10095/udp";
|
||||
};
|
||||
volumes = [
|
||||
"/srv/qbittorrent:/config/config"
|
||||
"/srv/video:/media/video"
|
||||
];
|
||||
};
|
||||
|
||||
radarr = lib.mkIf cfg.radarr.enable {
|
||||
hostname = "radarr";
|
||||
image = "ghcr.io/hotio/radarr:release-5.9.1.9070";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"7878:7878/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
environment = {
|
||||
PUID = toString config.users.users.radarr.uid;
|
||||
inherit PGID UMASK;
|
||||
TZ = config.time.timeZone;
|
||||
};
|
||||
volumes = [
|
||||
# TODO "config:/config"
|
||||
# TODO "data:/data"
|
||||
];
|
||||
};
|
||||
|
||||
sonarr = lib.mkIf cfg.sonarr.enable {
|
||||
hostname = "sonarr";
|
||||
image = "ghcr.io/hotio/sonarr:release-4.0.9.2244";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"8989:8989/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
environment = {
|
||||
PUID = toString config.users.users.sonarr.uid;
|
||||
inherit PGID UMASK;
|
||||
TZ = config.time.timeZone;
|
||||
};
|
||||
volumes = [
|
||||
# TODO "config:/config"
|
||||
# TODO "data:/data"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
17
modules/apps/calibre/default.nix
Normal file
17
modules/apps/calibre/default.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.calibre;
|
||||
in {
|
||||
options.homelab.apps.calibre.enable = lib.mkEnableOption "Calibre";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users.calibre = {
|
||||
uid = lib.mkForce 3010;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
};
|
||||
}
|
||||
12
modules/apps/default.nix
Normal file
12
modules/apps/default.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
imports = [
|
||||
./arr
|
||||
./calibre
|
||||
./gitea
|
||||
./jellyfin
|
||||
./plex
|
||||
./speedtest
|
||||
./technitium-dns
|
||||
./vaultwarden
|
||||
];
|
||||
}
|
||||
654
modules/apps/gitea/default.nix
Normal file
654
modules/apps/gitea/default.nix
Normal file
|
|
@ -0,0 +1,654 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.gitea;
|
||||
|
||||
networkName = "gitea";
|
||||
|
||||
UID = 3015;
|
||||
GID = config.users.groups.apps.gid;
|
||||
postgresPassword = "ChangeMe";
|
||||
repoDir = "/srv/git";
|
||||
webPort = 3000;
|
||||
sshPort = 2222;
|
||||
dbPort = 5432;
|
||||
redisPort = 6379;
|
||||
|
||||
title = "Hugo's Forge";
|
||||
slogan = "Forging ideas into reality.";
|
||||
description = "Personal git server for projects that don't need collaboration.";
|
||||
in {
|
||||
options.homelab.apps.gitea.enable = lib.mkEnableOption "Gitea";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
homelab = {
|
||||
users = {
|
||||
apps.enable = true;
|
||||
backup.enable = true;
|
||||
};
|
||||
|
||||
virtualisation.containers.enable = true;
|
||||
};
|
||||
|
||||
users.users.gitea = {
|
||||
uid = lib.mkForce UID;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.apps.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
|
||||
# Use filesystem mounts because rootless containers otherwise don't have access to the mount path (nested in docker directories).
|
||||
# You could probably fix this by modifying the access rights on the path, but what would the point of that be?
|
||||
fileSystems = {
|
||||
# Mount options:
|
||||
# - hard: retry requests indefinitely if the server becomes unresponsive.
|
||||
# - nosuid: prevent set-user-id and set-group-id bits
|
||||
"/srv/gitea-config" = {
|
||||
device = "192.168.0.11:/mnt/SMALL/CONFIG/GITEA";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"rw"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft" "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
|
||||
"nosuid"
|
||||
"tcp"
|
||||
];
|
||||
};
|
||||
|
||||
"/srv/gitea-git" = {
|
||||
device = "192.168.0.11:/mnt/SMALL/DATA/GIT";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"rw"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft" "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
|
||||
"nosuid"
|
||||
"tcp"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Make sure the Docker network exists.
|
||||
systemd.services."docker-${networkName}-create-network" = {
|
||||
description = "Create Docker network for ${networkName}";
|
||||
requiredBy = [
|
||||
"docker-gitea-db.service"
|
||||
"docker-gitea.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
if ! ${pkgs.docker}/bin/docker network ls | grep -q ${networkName}; then
|
||||
${pkgs.docker}/bin/docker network create ${networkName}
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers = {
|
||||
gitea-db = {
|
||||
hostname = "gitea-db";
|
||||
image = "postgres:15.8-alpine";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"5432:${toString dbPort}/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
environment = {
|
||||
POSTGRES_PASSWORD = "ChangeMe";
|
||||
PGDATA = "/var/lib/postgresql/data/pgdata";
|
||||
};
|
||||
volumes = [
|
||||
"gitea-db:/var/lib/postgresql/data/pgdata"
|
||||
];
|
||||
};
|
||||
|
||||
gitea-redis = {
|
||||
hostname = "gitea-redis";
|
||||
image = "redis:7.4.0-alpine3.20";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"6379:${toString redisPort}/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
volumes = [
|
||||
"gitea-redis:/data"
|
||||
];
|
||||
};
|
||||
|
||||
gitea = {
|
||||
hostname = "gitea";
|
||||
image = "codeberg.org/forgejo/forgejo:8.0.3-rootless";
|
||||
autoStart = true;
|
||||
user = "${toString UID}:${toString GID}";
|
||||
ports = [
|
||||
"3000:${toString webPort}/tcp"
|
||||
"2222:${toString sshPort}/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
dependsOn = [
|
||||
"gitea-db"
|
||||
"gitea-redis"
|
||||
];
|
||||
volumes = [
|
||||
"/srv/gitea-config:/var/lib/gitea"
|
||||
"/srv/gitea-git:/srv/git"
|
||||
"/etc/timezone:/etc/timezone:ro"
|
||||
"/etc/localtime:/etc/localtime:ro"
|
||||
];
|
||||
environmentFiles = [
|
||||
# NOTE Don't forget to create this file.
|
||||
# TODO Put in place using age(nix)?
|
||||
"/var/lib/gitea.env"
|
||||
];
|
||||
environment = {
|
||||
# App name that shows in every page title.
|
||||
FORGEJO__APP_NAME = title;
|
||||
# Shows a slogan near the App name in every page title.
|
||||
FORGEJO__APP_SLOGAN = slogan;
|
||||
# Defines how the AppDisplayName should be presented.
|
||||
#FORGEJO__APP_DISPLAY_NAME_FORMAT = "";
|
||||
# Will automaticaly detect the current user - but you can set it here.
|
||||
FORGEJO__RUN_USER = "gitea";
|
||||
# Application run mode, affects performance and debugging: "dev" or "prod", default is
|
||||
# "prod". Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are
|
||||
# treated as "prod" which is for production use.
|
||||
FORGEJO__RUN_MODE = "prod";
|
||||
# The working directory.
|
||||
#WORK_PATH = "";
|
||||
|
||||
# Disable SSH feature when not available.
|
||||
FORGEJO__server__DISABLE_SSH = "false";
|
||||
# Whether to use the builltin SSH server or not.
|
||||
FORGEJO__server__START_SSH_SERVER = "true";
|
||||
# Username to use for the builtin SSH server. If blank, then it is the value of RUN_USER.
|
||||
#FORGEJO__server__BUILTIN_SSH_SERVER_USER = "git";
|
||||
# Domain to be exposed in clone URL.
|
||||
#FORGEJO__server__SSH_DOMAIN = "";
|
||||
# SSH username displayed in clone URLs.
|
||||
#FORGEJO__server__SSH_USER = "git";
|
||||
# The network interface the builtin SSH server should listen on.
|
||||
#FORGEJO__server__SSH_LISTEN_HOST = "ens18";
|
||||
# Port number to be exposed in clone URL.
|
||||
FORGEJO__server__SSH_PORT = "22";
|
||||
# Port number the builtin SSH server should listen on.
|
||||
FORGEJO__server__SSH_LISTEN_PORT = toString sshPort;
|
||||
# Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
|
||||
FORGEJO__server__SSH_ROOT_PATH = "/var/lib/gitea/ssh";
|
||||
# Gitea will create a authorized_keys file by default when it is not using the internal ssh server
|
||||
# If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
|
||||
#FORGEJO__server__SSH_CREATE_AUTHORIZED_KEYS_FILE = "true";
|
||||
# Gitea will create a authorized_principals file by default when it is not using the internal ssh server
|
||||
# If you intend to use the AuthorizedPrincipalsCommand functionality then you should turn this off.
|
||||
#FORGEJO__server__SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE = "true";
|
||||
# For the built-in SSH server, choose the ciphers to support for SSH connections,
|
||||
# for system SSH this setting has no effect
|
||||
#FORGEJO__server__SSH_SERVER_CIPHERS = "chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com";
|
||||
# For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
|
||||
# for system SSH this setting has no effect
|
||||
#FORGEJO__server__SSH_SERVER_KEY_EXCHANGES = "curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1";
|
||||
# For the built-in SSH server, choose the MACs to support for SSH connections,
|
||||
# for system SSH this setting has no effect
|
||||
#FORGEJO__server__SSH_SERVER_MACS = "hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1";
|
||||
# For the built-in SSH server, choose the keypair to offer as the host key
|
||||
# The private key should be at SSH_SERVER_HOST_KEY and the public SSH_SERVER_HOST_KEY.pub
|
||||
# relative paths are made absolute relative to the %(APP_DATA_PATH)s
|
||||
FORGEJO__server__SSH_SERVER_HOST_KEYS = "/var/lib/gitea/ssh/forgejo.ed25519";
|
||||
# Directory to create temporary files in when testing public keys using ssh-keygen,
|
||||
# default is the system temporary directory.
|
||||
#FORGEJO__server__SSH_KEY_TEST_PATH = "";
|
||||
# Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
|
||||
#FORGEJO__server__SSH_KEYGEN_PATH = "";
|
||||
# Enable SSH Authorized Key Backup when rewriting all keys, default is false
|
||||
FORGEJO__server__SSH_AUTHORIZED_KEYS_BACKUP = "false";
|
||||
# ...
|
||||
# Enable exposure of SSH clone URL to anonymous visitors, default is false.
|
||||
FORGEJO__server__EXPOSE_ANONYMOUS = "false";
|
||||
# ...
|
||||
# Enables git-lfs support. true or false, default is false.
|
||||
FORGEJO__server__LFS_START_SERVER = "false";
|
||||
# ...
|
||||
|
||||
# Database to use. Either "mysql", "postgres" or "sqlite3".
|
||||
FORGEJO__database__DB_TYPE = "postgres";
|
||||
FORGEJO__database__HOST = "gitea-db:${toString dbPort}";
|
||||
FORGEJO__database__NAME = "gitea";
|
||||
FORGEJO__database__USER = "gitea";
|
||||
FORGEJO__database__PASSWD = postgresPassword;
|
||||
#FORGEJO__database__SCHEMA = "";
|
||||
#FORGEJO__database__SSL_MODE = "disable";
|
||||
|
||||
# Whether the installer is disabled (set to true to disable the installer).
|
||||
#FORGEJO__security__INSTALL_LOCK = "false";
|
||||
# Global security key that will be used.
|
||||
# This key is VERY IMPORTANT. If you lose it, the data encrypted by it can't be decrypted anymore.
|
||||
#FORGEJO__security__SECRET_KEY = "";
|
||||
# Alternatively, specify the location of the secret key.
|
||||
#FORGEJO__security__SECRET_KEY_URI = "file:/etc/gitea/secret_key";
|
||||
# ...
|
||||
|
||||
# IF the camo is enabled.
|
||||
#FORGEJO__camo__ENABLED = "false";
|
||||
# ....
|
||||
|
||||
# Enables OAuth2 provider
|
||||
FORGEJO__oauth2__ENABLED = "false";
|
||||
# ...
|
||||
|
||||
# Root path for the log files - defaults to %(GITEA_WORK_DIR)/log
|
||||
#FORGEJO__log__ROOT_PATH = "";
|
||||
# Either "console", "file" or "conn", default is "console"
|
||||
FORGEJO__log__MODE = "file";
|
||||
# Either "Trace", "Debug", "Info", "Warn", "Error" or "None", default is "Info".
|
||||
FORGEJO__log__LEVEL = "Warn";
|
||||
# ...
|
||||
# Collect SSH logs (Creates logs from ssh git requests)
|
||||
FORGEJO__log__ENABLE_SSH_LOG = "true";
|
||||
# ...
|
||||
|
||||
# The path of git executable. If empty, Gitea searches through the PATH environment.
|
||||
#FORGEJO__git__PATH = "";
|
||||
# ...
|
||||
FORGEJO__git_0x2E_timeout__MIGRATE = "600";
|
||||
FORGEJO__git_0x2E_timeout__MIRROR = "600";
|
||||
|
||||
# Time limit to confirm account/email registration.
|
||||
#FORGEJO__service__ACTIVE_CODE_LIVE_MINUTES = "180";
|
||||
# Time limit to perform the reset of a forgotten password.
|
||||
#FORGEJO__service__RESET_PASSWD_CODE_LIVE_MINUTES = "180";
|
||||
# Whether a new user needs to confirm their email when registering.
|
||||
FORGEJO__service__REGISTER_EMAIL_CONFIRM = "true";
|
||||
# Whether a new user needs to be confirmed manually after registration.
|
||||
FORGEJO__service__REGISTER_MANUAL_CONFIRM = "true";
|
||||
# List of domain names that are allowed to be used to register on a Gitea instance, wildcard is supported.
|
||||
#FORGEJO__service__EMAIL_DOMAIN_ALLOWLIST = "";
|
||||
# Comma-separated list of domain names that are not allowed to be used to register on a Gitea instance, wildcard is supported.
|
||||
#FORGEJO__service__EMAIL_DOMAIN_BLOCKLIST = "";
|
||||
# Disallow registration, only allow admins to create accounts.
|
||||
FORGEJO__service__DISABLE_REGISTRATION = "true";
|
||||
# Allow registration only using gitea itself, it works only when DISABLE_REGISTRATION is false.
|
||||
FORGEJO__service__ALLOW_ONLY_INTERNAL_REGISTRATION = "true";
|
||||
# Allow registration only using third-party services, it works only when DISABLE_REGISTRATION is false.
|
||||
FORGEJO__service__ALLOW_ONLY_EXTERNAL_REGISTRATION = "false";
|
||||
# User must sign in to view anything.
|
||||
FORGEJO__service__REQUIRE_SIGNIN_VIEW = "false";
|
||||
# Mail notification
|
||||
FORGEJO__service__ENABLE_NOTIFY_MAIL = "true";
|
||||
# This setting enables gitea to be signed in with HTTP BASIC Authentication using the user's password.
|
||||
# If you set this to false you will not be able to access the tokens endpoints on the API with your password.
|
||||
# Please note that setting this to false will not disable OAuth Basic or Basic authentication using a token.
|
||||
FORGEJO__service__ENABLE_BASIC_AUTHENTICATION = "false";
|
||||
# ...
|
||||
# Enable captcha validation for registration.
|
||||
FORGEJO__service__ENABLE_CAPTCHA = "true";
|
||||
# Enable this to require captcha validation for login.
|
||||
FORGEJO__service__REQUIRE_CAPTCHA_FOR_LOGIN = "true";
|
||||
# Requires captcha for external registrations
|
||||
#FORGEJO__service__REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA = "false";
|
||||
# Requires a password for external registrations.
|
||||
#FORGEJO__service__REQUIRE_EXTERNAL_REGISTRATION_PASSWORD = "false";
|
||||
# Type of captcha you want to use. Options: image, recaptcha, hcaptcha, mcaptcha, cfturnstile.
|
||||
FORGEJO__service__CAPTCHA_TYPE = "image";
|
||||
# ...
|
||||
# Default value for KeepEmailPrivate
|
||||
# Each new user will get the value of this setting copied into their profile
|
||||
FORGEJO__service__DEFAULT_KEEP_EMAIL_PRIVATE = "true";
|
||||
# Default value for AllowCreateOrganization
|
||||
# Every new user will have rights set to create organizations depending on this setting.
|
||||
FORGEJO__service__DEFAULT_ALLOW_CREATE_ORGANIZATION = "true";
|
||||
# Default value for IsRestricted
|
||||
# Every new user will have restricted permissions depending on this setting.
|
||||
FORGEJO__service__DEFAULT_USER_IS_RESTRICTED = "false";
|
||||
# Users will be able to use dots when choosing their username. Disabling this is
|
||||
# helpful if your usersare having issues with e.g. RSS feeds or advanced third-party
|
||||
# extensions that use strange regex patterns.
|
||||
FORGEJO__service__ALLOW_DOTS_IN_USERNAMES = "false";
|
||||
# Either "public", "limited" or "private", default is "public".
|
||||
# Limited is for users visible only to signed users.
|
||||
# Private is for users visible only to members of their organizations
|
||||
# Public is for users visible for everyone
|
||||
FORGEJO__service__DEFAULT_USER_VISIBILITY = "limited";
|
||||
# Set which visibility modes a user can have
|
||||
FORGEJO__service__ALLOWED_USER_VISIBILITY_MODES = "public,limited,private";
|
||||
# Either "public", "limited" or "private", default is "public".
|
||||
# Limited is for organizations visible only to signed users
|
||||
# Private is for organizations visible only to members of the organization
|
||||
# Public is for organizations visible to everyone
|
||||
FORGEJO__service__DEFAULT_ORG_VISIBILITY = "limited";
|
||||
# Default value for DefaultOrgMemberVisible
|
||||
# True will make the membership of the users visible when added to the organisation
|
||||
FORGEJO__service__DEFAULT_ORG_MEMBER_VISIBLE = "false";
|
||||
# Default value for EnableDependencies
|
||||
# Repositories will use dependencies by default depending on this setting
|
||||
#FORGEJO__service__DEFAULT_ENABLE_DEPENDENCIES = "true";
|
||||
# Dependencies can be added from any repository where the user is granted access or only from the current repository depending on this setting.
|
||||
#FORGEJO__service__ALLOW_CROSS_REPOSITORY_DEPENDENCIES = "true";
|
||||
# Default map service. No external API support has been included. A service has to allow
|
||||
# searching using URL parameters, the location will be appended to the URL as escaped query parameter.
|
||||
# Some example values are:
|
||||
# - OpenStreetMap: https://www.openstreetmap.org/search?query=
|
||||
# - Google Maps: https://www.google.com/maps/place/
|
||||
# - MapQuest: https://www.mapquest.com/search/
|
||||
# - Bing Maps: https://www.bing.com/maps?where1=
|
||||
#FORGEJO__service__USER_LOCATION_MAP_URL = "https://www.openstreetmap.org/search?query=";
|
||||
# Enable heatmap on users profiles.
|
||||
FORGEJO__service__ENABLE_USER_HEATMAP = "true";
|
||||
# Enable Timetracking
|
||||
FORGEJO__service__ENABLE_TIMETRACKING = "true";
|
||||
# Default value for EnableTimetracking
|
||||
# Repositories will use timetracking by default depending on this setting
|
||||
FORGEJO__service__DEFAULT_ENABLE_TIMETRACKING = "false";
|
||||
# Default value for AllowOnlyContributorsToTrackTime
|
||||
# Only users with write permissions can track time if this is true
|
||||
#FORGEJO__service__DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME = "true";
|
||||
# Value for the domain part of the user's email address in the git log if user
|
||||
# has set KeepEmailPrivate to true. The user's email will be replaced with a
|
||||
# concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS. Default
|
||||
# value is "noreply." + DOMAIN, where DOMAIN resolves to the value from server.DOMAIN
|
||||
# Note: do not use the <DOMAIN> notation below
|
||||
FORGEJO__service__NO_REPLY_ADDRESS = "noreply.depeuter.dev";
|
||||
# Show Registration button.
|
||||
FOGEJO__service__SHOW_REGISTRATION_BUTTON = "false";
|
||||
# Show milestones dashboard page - a view of all the user's milestones.
|
||||
#FORGEJO__service__SHOW_MILESTONES_DASHBOARD_PAGE = "true";
|
||||
# Default value for AutoWatchNewRepos
|
||||
# When adding a repo to a team or creating a new repo all team members will watch the
|
||||
# repo automatically if enabled
|
||||
#FORGEJO__service__AUTO_WATCH_NEW_REPOS = "true";
|
||||
# Default value for AutoWatchOnChanges
|
||||
# Make the user watch a repository When they commit for the first time
|
||||
#FORGEJO__service__AUTO_WATCH_ON_CHANGES = "false";
|
||||
# Minimum amount of time a user must exist before comments are kept when the user is deleted.
|
||||
#FORGEJO__service__USER_DELETE_WITH_COMMENTS_MAX_TIME = "0";
|
||||
# Valid site url schemes for user profiles
|
||||
#FORGEJO__service__VALID_SITE_URL_SCHEMES = "http,https";
|
||||
|
||||
# Enable repository badges (via shields.io or a similar generator)
|
||||
#FORGEJO__badges__ENABLED = "true";
|
||||
# ...
|
||||
|
||||
# Root path for storing all repository data. By default, it is set to %(APP_DATA_PATH)s/gitea-repositories.
|
||||
# A relative path is interpreted as _`AppWorkPath`_/%(ROOT)s
|
||||
FORGEJO__repository__ROOT = repoDir;
|
||||
# ...
|
||||
# Disable stars feature.
|
||||
FORGEJO__repository__DISABLE_STARS = "true";
|
||||
# Disable repository forking.
|
||||
#FORGEJO__repository__DISABLE_FORKS = "false";
|
||||
# The default branch name of new repositories
|
||||
FORGEJO__repository__DEFAULT_BRANCH = "main";
|
||||
# ...
|
||||
|
||||
# List of prefixes used in Pull Request title to mark them as Work In Progress (matched in a case-insensitive manner)
|
||||
FORGEJO__repository_0x2E_pull_0X2D_request__WORK_IN_PROGRESS_PREFIXES = "WIP:,[WIP],WIP";
|
||||
# ...
|
||||
# In the default merge message for squash commits walk all commits to include all authors in the Co-authored-by otherwise just use those in the limited list.
|
||||
FORGEJO__repository_0x2E_pull_0X2D_request__DEFAULT_MERGE_MESSAGE_ALL_AUTHORS = "true";
|
||||
# ...
|
||||
|
||||
# Enable cors headers (disabled by default)
|
||||
FORGEJO__cors__ENABLED = "true";
|
||||
# list of requesting origins that are allowed, eg: "https://*.example.com".
|
||||
FORGEJO__cors__ALLOW_DOMAINS = "https://git.depeuter.dev,http://192.168.0.24:${toString webPort}";
|
||||
|
||||
# Set the default theme for the Gitea install.
|
||||
FORGEJO__ui__DEFAULT_THEME = "gitea-auto";
|
||||
# All available themes. Allow users to select personalized themes regardless of `DEFAULT_THEME`.
|
||||
FORGEJO__ui__THEMES = "gitea-auto,gitea-light,gitea-dark,forgejo-auto,forgejo-light,forgejo-dark,forgejo-auto-deuteranopia-protanopia,forgejo-light-deuteranopia-protanopia,forgejo-dark-deuteranopia-protanopia,forgejo-auto-tritanopia,forgejo-light-tritanopia-forgejo-dark-tritanopia,github-auto,github,github-dark,edge-auto,edge-light,edge-dark,everforest-auto,everforest-light,everforest-dark,gruvbox-auto,gruvbox-light,gruvbox-dark,gruvbox-material-auto,grubox-material-dark,gruvbox-material-light,sonokai-andromeda,sonokai-atlantis,sonokai-espresso,sonokai-maia,sonokai-shusia,sonokai,catppuccin-frappe-green,catppuccin-frappe-teal,catppuccin-frappe-sky,catppuccin-frappe-sapphire,catppuccin-frappe-blue,catppuccin-frappe-lavender,catppuccin-macchiato-green,catppuccin-macchiato-teal,catppuccin-macchiato-sky,catppuccin-macchiato-sapphire,catppuccin-macchiato-blue,catppuccin-macchiato-lavender,catppuccin-mocha-green,catppuccin-mocha-teal,catppuccin-mocha-sky,catppuccin-mocha-sapphire,catppuccin-mocha-blue,catppuccin-mocha-lavender,nord,pitchblack,matrix,dark-arc";
|
||||
|
||||
FORGEJO__ui_0x2E_meta__AUTHOR = "${title} - ${slogan}";
|
||||
FORGEJO__ui_0x2E_meta__DESCRIPTION = description;
|
||||
FORGEJO__ui_0x2E_meta__KEYWORDS = "git,self-hosted,projects,code";
|
||||
|
||||
# Whether to render SVG files as images. If SVG rendering is disabled, SVG files are displayed as text and cannot be embedded in markdown files as images.
|
||||
FORGEJO__ui_0x2E_svg__ENABLE_RENDER = "true";
|
||||
|
||||
# ...
|
||||
# Enables math inline and block detection
|
||||
FORGEJO__markdown__ENABLE_MATH = "true";
|
||||
|
||||
# Define allowed algorithms and their minimum key length (use -1 to disable a type)
|
||||
#FORGEJO__ssh__0x2E__minimum_key_sizes__ED25519 = "256";
|
||||
#FORGEJO__ssh__0x2E__minimum_key_sizes__ECDSA = "256";
|
||||
FORGEJO__ssh_0x2E_minimum_key_sizes__RSA = "-1";
|
||||
FORGEJO__ssh_0x2E_minimum_key_sizes__DSA = "-1";
|
||||
|
||||
# ... indexer
|
||||
|
||||
# ... queue
|
||||
|
||||
# Disallow regular (non-admin) users from creating organizations.
|
||||
#FORGEJO__admin__DISABLE_REGULAR_ORG_CREATION = "false";
|
||||
# Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
|
||||
FORGEJO__admin__DEFAULT_EMAIL_NOTIFICATIONS = "enabled";
|
||||
# Send an email to all admins when a new user signs up to inform the admins about this act. Options: true, false
|
||||
FORGEJO__admin__SEND_NOTIFICATION_EMAIL_ON_NEW_USER = "true";
|
||||
# Disabled features for users, could be "deletion", "manage_ssh_keys","manage_gpg_keys" more features can be disabled in future
|
||||
# - deletion: a user cannot delete their own account
|
||||
# - manage_ssh_keys: a user cannot configure ssh keys
|
||||
# - manage_gpg_keys: a user cannot configure gpg keys
|
||||
#FORGEJO__admin__USER_DISABLED_FEATURES = "";
|
||||
# Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
|
||||
# - deletion: a user cannot delete their own account
|
||||
# - manage_ssh_keys: a user cannot configure ssh keys
|
||||
# - manage_gpg_keys: a user cannot configure gpg keys
|
||||
#FORGEJO__admin__EXTERNAL_USER_DISABLE_FEATURES = "";
|
||||
|
||||
# Whether to allow signin in via OpenID
|
||||
FORGEJO__openid__ENABLE_OPENID_SIGNIN = "false";
|
||||
# Whether to allow registering via OpenID
|
||||
# Do not include to rely on rhw DISABLE_REGISTRATION setting
|
||||
FORGEJO__openid__ENABLE_OPENID_SIGNUP = "false";
|
||||
# ...
|
||||
|
||||
# ... oath2_client
|
||||
|
||||
# ... webhook
|
||||
|
||||
FORGEJO__mailer__ENABLED = "true";
|
||||
# Buffer length of channel, keep it as it is if you don't know what it is.
|
||||
#FORGEJO__mailer__SEND_BUFFER_LEN = "100";
|
||||
# Prefix displayed before subject in mail.
|
||||
#FORGEJO__mailer__SUBJECT_PREFIX = "";
|
||||
# Mail server protocol. One of "smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy"
|
||||
FORGEJO__mailer__PROTOCOL = "smtps";
|
||||
# Mail server address
|
||||
FORGEJO__mailer__SMTP_ADDR = "smtp.gmail.com";
|
||||
# Mail server port. If no protocol is specified, it will be inferred by this setting.
|
||||
FORGEJO__mailer__SMTP_PORT = "465";
|
||||
# Enable HELO operation. Defaults to true.
|
||||
#FORGEJO__mailer__ENABLE_HELO = "true";
|
||||
# Custom hostname fo the HELO operation. If no value is provided, one is retrieved from
|
||||
# the system.
|
||||
#FORGEJO__mailer__HELO_HOSTNAME = "";
|
||||
# If set to 'true', completely ignores server certificate validation errors. UNSAFE!
|
||||
#FORGEJO__mailer__FORCE_TRUST_SERVER_CERT = "false";
|
||||
# Use client certificate in connection.
|
||||
#FORGEJO__mailer__USE_CLIENT_CERT = "false";
|
||||
#FORGEJO__mailer__CLIENT_CERT_FILE = "custom/mailer/cert.pem";
|
||||
#FORGEJO__mailer__CLIENT_KEY_FILE = "custom/mailer/key.pem";
|
||||
# Mail from address, RFC 5322. This can be just an email address, or the
|
||||
# `"Name" <email@example.com>` format.
|
||||
FORGEJO__mailer__FROM = ''"${title}" <git@depeuter.dev>'';
|
||||
# Sometimes it is helpful to use a different address on the envelope. Set this to use
|
||||
# ENVELOPE_FROM as the from on the envelope. Set to `<>` to send an empty address.
|
||||
#FORGEJO__mailer__ENVELOPE_FROM = "";
|
||||
# If gitea sends mails on behave of users, it will just use the name also displayed in the
|
||||
# WebUI. If you want e.g. `Mister X (by CodeIt) <gitea@codeit.net>`, set it to
|
||||
# `{{ .DisplayName }} (by {{ .AppName }})`.
|
||||
# Available Variables: `.DisplayName`, `.AppName` and `.Domain`.
|
||||
#FORGEJO__mailer__FROM_DISPLAY_NAME_FORMAT = "{{ .DisplayName }}";
|
||||
# Mailer user name and password, if required by provider.
|
||||
#FORGEJO__mailer__USER = "";
|
||||
# Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
#FORGEJO__mailer__PASSWD = "";
|
||||
# Send mails only in plain text, without HTML alternative
|
||||
#FORGEJO__mailer__SEND_AS_PLAIN_TEXT = "false";
|
||||
# Specify an alternative sendmail binary
|
||||
#FORGEJO__mailer__SENDMAIL_PATH = "sendmail";
|
||||
# Specify any extra sendmail arguments
|
||||
# WARNING: if your sendmail program interprets options you should set this to "--" or terminate these args with "--"
|
||||
#FORGEJO__mailer__SENDMAIL_ARGS = "";
|
||||
# Timeout for Sendmail
|
||||
#FORGEJO__mailer__SENDMAIL_TIMEOUT = "5m";
|
||||
# convert \r\n to \n for Sendmail
|
||||
#FORGEJO__mailer__SENDMAIL_CONVERT_CRLF = "true";
|
||||
|
||||
# ... email.incoming
|
||||
|
||||
# Either "memory", "redis", "memcache", or "twoqueue". default is "memory"
|
||||
FORGEJO__cache__ADAPTER = "redis";
|
||||
# For "memory" only, GC interval in seconds, default is 60.
|
||||
#FORGEJO__cache__INTERVAL = "60";
|
||||
# For "redis" and "memcache", connection host address
|
||||
# redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for a Redis cluster)
|
||||
# memcache: `127.0.0.1:11211`
|
||||
# twoqueue: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000`
|
||||
FORGEJO__cache__HOST = "redis://gitea-redis:${toString redisPort}/0?pool_size=100&idle_timeout=180s";
|
||||
# Time to keep items in cache if not used, default is 16 hours.
|
||||
# Setting it to -1 disables caching
|
||||
FORGEJO__cache__ITEM_TTL = "16h";
|
||||
# Time to keep items in cache if not used, default is 8760 hours.
|
||||
# Setting it to -1 disables caching
|
||||
FORGEJO__cache_0X2E_last_0X2D_commit__ITEM_TTL = "8760h";
|
||||
# Only enable the cache when repository's commits count great than
|
||||
FORGEJO__cache_0X2E_last_0X2D_commit__COMMITS_COUNT = "100";
|
||||
|
||||
# Either "memory", "file", "redis", "db", "mysql", "couchbase", "memcache" or "postgres"
|
||||
# Default is "memory". "db" will reuse the configuration in [database]
|
||||
#FORGEJO__session__PROVIDER = "memory";
|
||||
# Provider config options
|
||||
# memory: doesn't have any config yet
|
||||
# file: session file path, e.g. `data/sessions`
|
||||
# redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for a Redis cluster)
|
||||
# mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||
#FORGEJO__session__PROVIDER_CONFIG = "data/sessions"; # Relative paths will be made absolute against _`AppWorkPath`_.
|
||||
# Session cookie name
|
||||
FORGEJO__session__COOKIE_NAME = "i_like_tibo";
|
||||
# If you use session in https only: true or false. If not set, it defaults to `true` if the ROOT_URL is an HTTPS URL.
|
||||
FORGEJO__session__COOKIE_SECURE = "true";
|
||||
# Session GC time interval in seconds, default is 86400 (1 day)
|
||||
#FORGEJO__session__GC_0X2E_INTERVAL_0X2E_TIME = "86400";
|
||||
# Session life time in seconds, default is 86400 (1 day)
|
||||
#FORGEJO__session__SESSION_0X2E_LIFE_0X2E_TIME = "86400";
|
||||
# Cookie domain name. Default is empty
|
||||
FORGEJO__session__DOMAIN = "git.depeuter.dev";
|
||||
# SameSite settings. Either "none", "lax", or "strict"
|
||||
FORGEJO__session__SAME_SITE = "strict";
|
||||
|
||||
# How Gitea deals with missing repository avatars
|
||||
# none = no avatar will be displayed; random = random avatar will be displayed; image = default image will be used
|
||||
#FORGEJO__picture__REPOSITORY_AVATAR_FALLBACK = "none";
|
||||
#FORGEJO__picture__REPOSITORY_AVATAR_FALLBACK_IMAGE = "/img/repo_default.png";
|
||||
# Max Width and Height of uploaded avatars.
|
||||
# This is to limit the amount of RAM used when resizing the image.
|
||||
FORGEJO__picture__AVATAR_MAX_WIDTH = "10000";
|
||||
FORGEJO__picture__AVATAR_MAX_HEIGTH = "10000";
|
||||
# The multiplication factor for rendered avatar images.
|
||||
# Larger values result in finer rendering on HiDPI devices.
|
||||
#FORGEJO__picture__AVATAR_RENDERED_SIZE_FACTOR = "2";
|
||||
# Maximum allowed file size for uploaded avatars.
|
||||
# This is to limit the amount of RAM used when resizing the image.
|
||||
#FORGEJO__picture__AVATAR_MAX_FILE_SIZE = "1048576";
|
||||
# If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting.
|
||||
#FORGEJO__picture__AVATAR_MAX_ORIGIN_SIZE = "262144";
|
||||
# Chinese users can choose "duoshuo"
|
||||
# or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
||||
#FORGEJO__picture__GRAVATAR_SOURCE = "gravatar";
|
||||
# This value will always be true in offline mode.
|
||||
#FORGEJO__picture__DISABLE_GRAVATAR = "false";
|
||||
# Federated avatar lookup uses DNS to discover avatar associated.
|
||||
# with emails, see https://www.libravatar.org
|
||||
# This value will always be false in offline mode or when Gravatar is disabled.
|
||||
#FORGEJO__picture__ENABLE_FEDERATED_AVATAR = "false";
|
||||
|
||||
# ... attachment
|
||||
|
||||
# ... time
|
||||
|
||||
# ... cron
|
||||
|
||||
# Enables the mirror functionality. Set to **false** to disable all mirrors. Pre-existing mirrors remain valid but won't be updated; may be converted to regular repo.
|
||||
FORGEJO__mirror__ENABLED = "true";
|
||||
# Disable the creation of **new** pull mirrors. Pre-existing mirrors remain valid. Will be ignored if `mirror.ENABLED` is `false`.
|
||||
FORGEJO__mirror__DISABLE_NEW_PULL = "false";
|
||||
# Disable the creation of **new** push mirrors. Pre-existing mirrors remain valid. Will be ignored if `mirror.ENABLED` is `false`.
|
||||
FORGEJO__mirror__DISABLE_NEW_PUSH = "false";
|
||||
# Default interval as a duration between each check
|
||||
FORGEJO__mirror__DEFAULT_INTERVAL = "1h";
|
||||
# Min interval as a duration must be > 1m
|
||||
FORGEJO__mirror__MIN_INTERVAL = "5m";
|
||||
|
||||
# ... api
|
||||
|
||||
# ... i18n
|
||||
|
||||
# .. highlight.mapping
|
||||
|
||||
# Show version information about Gitea and Go in the footer
|
||||
FORGEJO__other__SHOW_FOOTER_VERSION = "false";
|
||||
# Show template execution time in the footer
|
||||
FORGEJO__other__SHOW_FOOTER_TEMPLATE_LOAD_TIME = "false";
|
||||
# Show the "powered by" text in the footer
|
||||
FORGEJO__other__SHOW_FOOTER_POWERED_BY = "false";
|
||||
# Generate sitemap. Defaults to `true`.
|
||||
FORGEJO__other__ENABLE_SITEMAP = "true";
|
||||
# Enable/Disable RSS/Atom feed
|
||||
FORGEJO__other__ENABLE_FEED = "true";
|
||||
|
||||
# ... markup
|
||||
|
||||
# ... metrics
|
||||
|
||||
# ... migrations
|
||||
|
||||
# ... f3
|
||||
|
||||
# Enable/Disable federation capabilities
|
||||
FORGEJO__federation_ENABLED = "false";
|
||||
# ...
|
||||
|
||||
# Enable/Disable package registry capabilities
|
||||
FORGEJO__packages__ENABLED = "true";
|
||||
|
||||
# ... storage
|
||||
|
||||
# Repo-archive storage will override storage.
|
||||
#FORGEJO__repo_0X2D_archive__STORAGE_TYPE = "local";
|
||||
# Where your lfs files reside, default is data/lfs
|
||||
FORGEJO__repo_0X2D_archive__PATH = "";
|
||||
# Override the minio base path if storage type is minio.
|
||||
#FORGEJO__repo_0X2D_archive__MINIO_BASE_PATH = "";
|
||||
|
||||
# lfs storage will override storage.
|
||||
#FORGEJO__lfs__STORAGE_TYPE = "local";
|
||||
# Where your lfs files reside, default is data/lfs
|
||||
FORGEJO__lfs__PATH = "";
|
||||
# Override the minio base path if storage is set to minio.
|
||||
#FORGEJO__lfs__MINIO_BASE_PATH = "lfs/";
|
||||
|
||||
# Enable the proxy, all requests to external via HTTP will be affected
|
||||
FORGEJO__proxy__PROXY_ENABLED = "false";
|
||||
# Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy/no_proxy
|
||||
#FORGEJO__proxy__PROXY_URL = "";
|
||||
# Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
|
||||
#FORGEJO__proxy__PROXY_HOSTS = "";
|
||||
|
||||
# Enable/Disable actions capabilities
|
||||
FORGEJO__actions__ENABLED = "true";
|
||||
# Default address to get action plugins, e.g. the default value means downloading from "https://code.forgejo.org/actions/checkout" for "uses: actions/checkout@v3"
|
||||
#FORGEJO__actions__DEFAULT_ACTIONS_URL = "https://code.forgejo.org";
|
||||
# ...
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
155
modules/apps/jellyfin/default.nix
Normal file
155
modules/apps/jellyfin/default.nix
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.jellyfin;
|
||||
|
||||
networkName = "jellyfin";
|
||||
|
||||
UID = 3008;
|
||||
GID = config.users.groups.media.gid;
|
||||
in {
|
||||
options.homelab.apps.jellyfin.enable = lib.mkEnableOption "Jellyfin using Docker";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
homelab = {
|
||||
users = {
|
||||
apps.enable = true;
|
||||
media.enable = true;
|
||||
};
|
||||
virtualisation.containers.enable = true;
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/srv/audio" = {
|
||||
device = "192.168.0.11:/mnt/SMALL/MEDIA/AUDIO";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"ro"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft"
|
||||
"timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
|
||||
"nosuid" "tcp"
|
||||
];
|
||||
};
|
||||
|
||||
"/srv/video" = {
|
||||
device = "192.168.0.11:/mnt/SMALL/MEDIA/VIDEO";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"ro"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft"
|
||||
"timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
|
||||
"nosuid" "tcp"
|
||||
];
|
||||
};
|
||||
|
||||
"/srv/homevideo" = {
|
||||
device = "192.168.0.11:/mnt/BIG/MEDIA/HOMEVIDEO/ARCHIVE";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"ro"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft"
|
||||
"timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
|
||||
"nosuid" "tcp"
|
||||
];
|
||||
};
|
||||
|
||||
"/srv/photo" = {
|
||||
device = "192.168.0.11:/mnt/BIG/MEDIA/PHOTO/ARCHIVE";
|
||||
fsType = "nfs";
|
||||
options = [
|
||||
"ro"
|
||||
"nfsvers=4.2"
|
||||
"async" "soft"
|
||||
"timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
|
||||
"nosuid" "tcp"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
users.users.jellyfin = {
|
||||
uid = lib.mkForce UID;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.apps.name;
|
||||
extraGroups = [
|
||||
config.users.groups.media.name
|
||||
];
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
|
||||
# Make sure the Docker network exists.
|
||||
systemd.services."docker-${networkName}-create-network" = {
|
||||
description = "Create Docker network for ${networkName}";
|
||||
requiredBy = [
|
||||
"docker-jellyfin.service"
|
||||
"docker-feishin.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
if ! ${pkgs.docker}/bin/docker network ls | grep -q ${networkName}; then
|
||||
${pkgs.docker}/bin/docker network create ${networkName}
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers = {
|
||||
jellyfin = {
|
||||
hostname = "jellyfin";
|
||||
image = "jellyfin/jellyfin:10.10.0";
|
||||
user = "${toString UID}:${toString GID}";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"8096:8096/tcp"
|
||||
# "8920:8920/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
"--device=nvidia.com/gpu=all" # Equivalent to --gpus=all
|
||||
];
|
||||
volumes = [
|
||||
"jellyfin-config:/config"
|
||||
"cache:/cache"
|
||||
|
||||
"/srv/audio:/media/audio"
|
||||
"/srv/video:/media/video"
|
||||
"/srv/homevideo:/media/homevideo"
|
||||
"/srv/photo:/media/photo"
|
||||
];
|
||||
environment = {
|
||||
# TODO
|
||||
};
|
||||
};
|
||||
|
||||
feishin = {
|
||||
hostname = "feishin";
|
||||
image = "ghcr.io/jeffvli/feishin:0.7.1";
|
||||
ports = [
|
||||
"9180:9180/tcp" # Web player (HTTP)
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
environment = {
|
||||
# pre defined server name
|
||||
SERVER_NAME = "Hugo";
|
||||
# When true AND name/type/url are set, only username/password can be toggled
|
||||
SERVER_LOCK = "true";
|
||||
# Either "jellyfin" or "navidrome"
|
||||
SERVER_TYPE = "jellyfin";
|
||||
# http://address:port
|
||||
SERVER_URL= "https://jelly.depeuter.dev";
|
||||
TZ = config.time.timeZone;
|
||||
};
|
||||
labels = {
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
50
modules/apps/plex/default.nix
Normal file
50
modules/apps/plex/default.nix
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.plex;
|
||||
in {
|
||||
options.homelab.apps.plex.enable = lib.mkEnableOption "Plex";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users.plex = {
|
||||
uid = lib.mkForce 3009;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers = {
|
||||
plex = {
|
||||
hostname = "plex";
|
||||
image = "plexinc/pms-docker:1.41.0.8992-8463ad060";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"32400:32400/tcp" # Plex Media Server
|
||||
"1900:1900/udp" # Plex DLNA Server
|
||||
"32469:32469/tcp" # Plex DLNA Server
|
||||
"32410:32410/udp" # GDM network discovery
|
||||
"32412:32412/udp" # GDM network discovery
|
||||
"32413:32413/udp" # GDM network discovery
|
||||
"32414:32414/udp" # GDM network discovery
|
||||
# "8324:8324/tcp" # Controlling Plex for Roku via Plex Companion
|
||||
];
|
||||
environment = {
|
||||
ADVERTISE_AP = "..."; # TODO Configure ip
|
||||
ALLOWED_NETWORKS = "192.168.0.0/24,172.16.0.0/16";
|
||||
CHANGE_CONFIG_DIR_OWNERSHIP = "false";
|
||||
HOSTNAME = "PlexServer";
|
||||
PLEX_CLAIM = "..."; # TODO Add token
|
||||
PLEX_UID = config.users.users.plex.uid;
|
||||
PLEX_GID = config.users.groups.media.gid;
|
||||
TZ = config.time.timeZone;
|
||||
};
|
||||
volumes = [
|
||||
# TODO "config:/var/lib/plexmediaserver"
|
||||
# TODO "transcode-temp:/transcode"
|
||||
# TODO "media:/data"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
27
modules/apps/speedtest/default.nix
Normal file
27
modules/apps/speedtest/default.nix
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.speedtest;
|
||||
in {
|
||||
options.homelab.apps.speedtest.enable = lib.mkEnableOption "Speedtest";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
homelab.virtualisation.containers.enable = true;
|
||||
|
||||
virtualisation.oci-containers.containers.speedtest = {
|
||||
hostname = "speedtest";
|
||||
image = "openspeedtest/latest:v2.0.5";
|
||||
ports = [
|
||||
"3000:3000"
|
||||
"3001:3001"
|
||||
];
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.speedtest.rule" = "Host(`speedtest.${config.networking.hostName}.${config.networking.domain}`)";
|
||||
"traefik.http.services.speedtest.loadbalancer.server.port" = "9090";
|
||||
"traefik.tls.options.default.minVersion" = "VersionTLS13";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
73
modules/apps/technitium-dns/default.nix
Normal file
73
modules/apps/technitium-dns/default.nix
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.technitiumDNS;
|
||||
in {
|
||||
options.homelab.apps.technitiumDNS.enable = lib.mkEnableOption "Technitium DNS";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
homelab.virtualisation.containers.enable = true;
|
||||
|
||||
virtualisation.oci-containers.containers.technitium-dns = {
|
||||
hostname = "technitium-dns";
|
||||
image = "technitium/dns-server:12.1";
|
||||
ports = [
|
||||
# "5380:5380/tcp" #DNS web console (HTTP)
|
||||
# "53443:53443/tcp" #DNS web console (HTTPS)
|
||||
"53:53/udp" #DNS service
|
||||
"53:53/tcp" #DNS service
|
||||
# "853:853/udp" #DNS-over-QUIC service
|
||||
# "853:853/tcp" #DNS-over-TLS service
|
||||
# "443:443/udp" #DNS-over-HTTPS service (HTTP/3)
|
||||
# "443:443/tcp" #DNS-over-HTTPS service (HTTP/1.1, HTTP/2)
|
||||
# "80:80/tcp" #DNS-over-HTTP service (use with reverse proxy or certbot certificate renewal)
|
||||
# "8053:8053/tcp" #DNS-over-HTTP service (use with reverse proxy)
|
||||
# "67:67/udp" #DHCP service
|
||||
];
|
||||
environment = {
|
||||
# The primary domain name used by this DNS Server to identify itself.
|
||||
DNS_SERVER_DOMAIN = config.networking.hostName;
|
||||
# DNS Server will use IPv6 for querying whenever possible with this option enabled.
|
||||
DNS_SERVER_PREFER_IPV6 = "true";
|
||||
# The TCP port number for the DNS web console over HTTP protocol.
|
||||
# DNS_SERVER_WEB_SERVICE_HTTP_PORT=5380
|
||||
# The TCP port number for the DNS web console over HTTPS protocol.
|
||||
# DNS_SERVER_WEB_SERVICE_HTTPS_PORT=53443
|
||||
# Enables HTTPS for the DNS web console.
|
||||
# DNS_SERVER_WEB_SERVICE_ENABLE_HTTPS=false
|
||||
# Enables self signed TLS certificate for the DNS web console.
|
||||
# DNS_SERVER_WEB_SERVICE_USE_SELF_SIGNED_CERT=false
|
||||
# Enables DNS server optional protocol DNS-over-HTTP on TCP port 8053 to be used with a TLS terminating reverse proxy like nginx.
|
||||
# DNS_SERVER_OPTIONAL_PROTOCOL_DNS_OVER_HTTP=false
|
||||
# Recursion options: Allow, Deny, AllowOnlyForPrivateNetworks, UseSpecifiedNetworks.
|
||||
#nDNS_SERVER_RECURSION=AllowOnlyForPrivateNetworks
|
||||
# Comma separated list of IP addresses or network addresses to deny recursion. Valid only for `UseSpecifiedNetworks` recursion option.
|
||||
# DNS_SERVER_RECURSION_DENIED_NETWORKS=1.1.1.0/24
|
||||
# Comma separated list of IP addresses or network addresses to allow recursion. Valid only for `UseSpecifiedNetworks` recursion option.
|
||||
# DNS_SERVER_RECURSION_ALLOWED_NETWORKS=127.0.0.1, 192.168.1.0/24
|
||||
# Sets the DNS server to block domain names using Blocked Zone and Block List Zone.
|
||||
DNS_SERVER_ENABLE_BLOCKING = "false";
|
||||
# Specifies if the DNS Server should respond with TXT records containing a blocked domain report for TXT type requests.
|
||||
# DNS_SERVER_ALLOW_TXT_BLOCKING_REPORT=false
|
||||
# A comma separated list of block list URLs.
|
||||
# DNS_SERVER_BLOCK_LIST_URLS=
|
||||
#Comma separated list of forwarder addresses.
|
||||
DNS_SERVER_FORWARDERS="195.130.130.2,195.130.131.2";
|
||||
# Forwarder protocol options: Udp, Tcp, Tls, Https, HttpsJson.
|
||||
# DNS_SERVER_FORWARDER_PROTOCOL=Tcp
|
||||
# Enable this option to use local time instead of UTC for logging.
|
||||
# DNS_SERVER_LOG_USING_LOCAL_TIME=true
|
||||
};
|
||||
volumes = [
|
||||
"technitium_dns:/etc/dns"
|
||||
];
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.technitium-dns.rule" = "Host(`dns.${config.networking.hostName}.${config.networking.domain}`)";
|
||||
"traefik.http.services.technitium-dns.loadbalancer.server.port" = "5380";
|
||||
"traefik.tls.options.default.minVersion" = "VersionTLS13";
|
||||
};
|
||||
autoStart = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
636
modules/apps/vaultwarden/default.nix
Normal file
636
modules/apps/vaultwarden/default.nix
Normal file
|
|
@ -0,0 +1,636 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.apps.vaultwarden;
|
||||
|
||||
networkName = "vaultwarden";
|
||||
in {
|
||||
options.homelab.apps.vaultwarden.enable = lib.mkEnableOption "Vaultwarden";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
homelab = {
|
||||
# Allow remote backups.
|
||||
users.backup.enable = true;
|
||||
|
||||
virtualisation.containers.enable = true;
|
||||
};
|
||||
|
||||
# Make sure the Docker network exists.
|
||||
systemd.services."docker-${networkName}-create-network" = {
|
||||
description = "Create Docker network for ${networkName}";
|
||||
requiredBy = [
|
||||
"docker-vaultwarden-db.service"
|
||||
"docker-vaultwarden.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
if ! ${pkgs.docker}/bin/docker network ls | grep -q ${networkName}; then
|
||||
${pkgs.docker}/bin/docker network create ${networkName}
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.containers = {
|
||||
vaultwarden-db = {
|
||||
hostname = "vaultwarden-db";
|
||||
image = "postgres:15.8-alpine";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"5432:5432/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
environment = {
|
||||
POSTGRES_PASSWORD = "ChangeMe";
|
||||
PGDATA = "/var/lib/postgresql/data/pgdata";
|
||||
};
|
||||
volumes = [
|
||||
"vaultwarden-db:/var/lib/postgresql/data"
|
||||
];
|
||||
};
|
||||
|
||||
vaultwarden = let
|
||||
dataDir = "/data";
|
||||
in {
|
||||
hostname = "vaultwarden";
|
||||
image = "vaultwarden/server:1.30.5-alpine";
|
||||
autoStart = true;
|
||||
ports = [
|
||||
"10102:80/tcp"
|
||||
];
|
||||
extraOptions = [
|
||||
"--network=${networkName}"
|
||||
];
|
||||
dependsOn = [
|
||||
"vaultwarden-db"
|
||||
];
|
||||
volumes = [
|
||||
"vaultwarden:${dataDir}"
|
||||
];
|
||||
environmentFiles = [
|
||||
# NOTE Don't forget to create this file
|
||||
# TODO Put in place using age(nix)?
|
||||
"/var/lib/vaultwarden.env"
|
||||
];
|
||||
environment = {
|
||||
####################
|
||||
### Data folders ###
|
||||
####################
|
||||
|
||||
## Main data folder
|
||||
DATA_FOLDER = dataDir;
|
||||
|
||||
## Individual folders, these override %DATA_FOLDER%
|
||||
# ICON_CACHE_FOLDER=data/icon_cache
|
||||
# ATTACHMENTS_FOLDER=data/attachments
|
||||
# SENDS_FOLDER=data/sends
|
||||
# TMP_FOLDER=data/tmp
|
||||
|
||||
## Templates data folder, by default uses embedded templates
|
||||
## Check source code to see the format
|
||||
# TEMPLATES_FOLDER=data/templates
|
||||
## Automatically reload the templates for every request, slow, use only for development
|
||||
# RELOAD_TEMPLATES=false
|
||||
|
||||
## Web vault settings
|
||||
# WEB_VAULT_FOLDER=web-vault/
|
||||
# WEB_VAULT_ENABLED=true
|
||||
|
||||
#########################
|
||||
### Database settings ###
|
||||
#########################
|
||||
|
||||
## Database URL
|
||||
## When using SQLite, this is the path to the DB file, default to %DATA_FOLDER%/db.sqlite3
|
||||
# DATABASE_URL=data/db.sqlite3
|
||||
## When using MySQL, specify an appropriate connection URI.
|
||||
## Details: https://docs.diesel.rs/2.1.x/diesel/mysql/struct.MysqlConnection.html
|
||||
# DATABASE_URL=mysql://user:password@host[:port]/database_name
|
||||
## When using PostgreSQL, specify an appropriate connection URI (recommended)
|
||||
## or keyword/value connection string.
|
||||
## Details:
|
||||
## - https://docs.diesel.rs/2.1.x/diesel/pg/struct.PgConnection.html
|
||||
## - https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
|
||||
DATABASE_URL = "postgresql://vaultwarden:ChangeMe@vaultwarden-db:5432/vaultwarden";
|
||||
|
||||
## Enable WAL for the DB
|
||||
## Set to false to avoid enabling WAL during startup.
|
||||
## Note that if the DB already has WAL enabled, you will also need to disable WAL in the DB,
|
||||
## this setting only prevents Vaultwarden from automatically enabling it on start.
|
||||
## Please read project wiki page about this setting first before changing the value as it can
|
||||
## cause performance degradation or might render the service unable to start.
|
||||
# ENABLE_DB_WAL=true
|
||||
|
||||
## Database connection retries
|
||||
## Number of times to retry the database connection during startup, with 1 second delay between each retry, set to 0 to retry indefinitely
|
||||
# DB_CONNECTION_RETRIES=15
|
||||
|
||||
## Database timeout
|
||||
## Timeout when acquiring database connection
|
||||
# DATABASE_TIMEOUT=30
|
||||
|
||||
## Database max connections
|
||||
## Define the size of the connection pool used for connecting to the database.
|
||||
# DATABASE_MAX_CONNS=10
|
||||
|
||||
## Database connection initialization
|
||||
## Allows SQL statements to be run whenever a new database connection is created.
|
||||
## This is mainly useful for connection-scoped pragmas.
|
||||
## If empty, a database-specific default is used:
|
||||
## - SQLite: "PRAGMA busy_timeout = 5000; PRAGMA synchronous = NORMAL;"
|
||||
## - MySQL: ""
|
||||
## - PostgreSQL: ""
|
||||
# DATABASE_CONN_INIT=""
|
||||
|
||||
#################
|
||||
### WebSocket ###
|
||||
#################
|
||||
|
||||
## Enable websocket notifications
|
||||
# ENABLE_WEBSOCKET=true
|
||||
|
||||
##########################
|
||||
### Push notifications ###
|
||||
##########################
|
||||
|
||||
## Enables push notifications (requires key and id from https://bitwarden.com/host)
|
||||
## Details about mobile client push notification:
|
||||
## - https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Mobile-Client-push-notification
|
||||
# PUSH_ENABLED=false
|
||||
# PUSH_INSTALLATION_ID=CHANGEME
|
||||
# PUSH_INSTALLATION_KEY=CHANGEME
|
||||
|
||||
# WARNING: Do not modify the following settings unless you fully understand their implications!
|
||||
# Default Push Relay and Identity URIs
|
||||
# PUSH_RELAY_URI=https://push.bitwarden.com
|
||||
# PUSH_IDENTITY_URI=https://identity.bitwarden.com
|
||||
# European Union Data Region Settings
|
||||
# If you have selected "European Union" as your data region, use the following URIs instead.
|
||||
# PUSH_RELAY_URI=https://api.bitwarden.eu
|
||||
# PUSH_IDENTITY_URI=https://identity.bitwarden.eu
|
||||
|
||||
#####################
|
||||
### Schedule jobs ###
|
||||
#####################
|
||||
|
||||
## Job scheduler settings
|
||||
##
|
||||
## Job schedules use a cron-like syntax (as parsed by https://crates.io/crates/cron),
|
||||
## and are always in terms of UTC time (regardless of your local time zone settings).
|
||||
##
|
||||
## The schedule format is a bit different from crontab as crontab does not contains seconds.
|
||||
## You can test the the format here: https://crontab.guru, but remove the first digit!
|
||||
## SEC MIN HOUR DAY OF MONTH MONTH DAY OF WEEK
|
||||
## "0 30 9,12,15 1,15 May-Aug Mon,Wed,Fri"
|
||||
## "0 30 * * * * "
|
||||
## "0 30 1 * * * "
|
||||
##
|
||||
## How often (in ms) the job scheduler thread checks for jobs that need running.
|
||||
## Set to 0 to globally disable scheduled jobs.
|
||||
# JOB_POLL_INTERVAL_MS=30000
|
||||
##
|
||||
## Cron schedule of the job that checks for Sends past their deletion date.
|
||||
## Defaults to hourly (5 minutes after the hour). Set blank to disable this job.
|
||||
# SEND_PURGE_SCHEDULE="0 5 * * * *"
|
||||
##
|
||||
## Cron schedule of the job that checks for trashed items to delete permanently.
|
||||
## Defaults to daily (5 minutes after midnight). Set blank to disable this job.
|
||||
# TRASH_PURGE_SCHEDULE="0 5 0 * * *"
|
||||
##
|
||||
## Cron schedule of the job that checks for incomplete 2FA logins.
|
||||
## Defaults to once every minute. Set blank to disable this job.
|
||||
# INCOMPLETE_2FA_SCHEDULE="30 * * * * *"
|
||||
##
|
||||
## Cron schedule of the job that sends expiration reminders to emergency access grantors.
|
||||
## Defaults to hourly (3 minutes after the hour). Set blank to disable this job.
|
||||
# EMERGENCY_NOTIFICATION_REMINDER_SCHEDULE="0 3 * * * *"
|
||||
##
|
||||
## Cron schedule of the job that grants emergency access requests that have met the required wait time.
|
||||
## Defaults to hourly (7 minutes after the hour). Set blank to disable this job.
|
||||
# EMERGENCY_REQUEST_TIMEOUT_SCHEDULE="0 7 * * * *"
|
||||
##
|
||||
## Cron schedule of the job that cleans old events from the event table.
|
||||
## Defaults to daily. Set blank to disable this job. Also without EVENTS_DAYS_RETAIN set, this job will not start.
|
||||
# EVENT_CLEANUP_SCHEDULE="0 10 0 * * *"
|
||||
## Number of days to retain events stored in the database.
|
||||
## If unset (the default), events are kept indefinitely and the scheduled job is disabled!
|
||||
# EVENTS_DAYS_RETAIN=
|
||||
##
|
||||
## Cron schedule of the job that cleans old auth requests from the auth request.
|
||||
## Defaults to every minute. Set blank to disable this job.
|
||||
# AUTH_REQUEST_PURGE_SCHEDULE="30 * * * * *"
|
||||
##
|
||||
## Cron schedule of the job that cleans expired Duo contexts from the database. Does nothing if Duo MFA is disabled or set to use the legacy iframe prompt.
|
||||
## Defaults to every minute. Set blank to disable this job.
|
||||
# DUO_CONTEXT_PURGE_SCHEDULE="30 * * * * *"
|
||||
|
||||
########################
|
||||
### General settings ###
|
||||
########################
|
||||
|
||||
## Domain settings
|
||||
## The domain must match the address from where you access the server
|
||||
## It's recommended to configure this value, otherwise certain functionality might not work,
|
||||
## like attachment downloads, email links and U2F.
|
||||
## For U2F to work, the server must use HTTPS, you can use Let's Encrypt for free certs
|
||||
## To use HTTPS, the recommended way is to put Vaultwarden behind a reverse proxy
|
||||
## Details:
|
||||
## - https://github.com/dani-garcia/vaultwarden/wiki/Enabling-HTTPS
|
||||
## - https://github.com/dani-garcia/vaultwarden/wiki/Proxy-examples
|
||||
## For development
|
||||
# DOMAIN=http://localhost
|
||||
## For public server
|
||||
DOMAIN = "https://vault.depeuter.dev";
|
||||
## For public server (URL with port number)
|
||||
# DOMAIN=https://vw.domain.tld:8443
|
||||
## For public server (URL with path)
|
||||
# DOMAIN=https://domain.tld/vw
|
||||
|
||||
## Controls whether users are allowed to create Bitwarden Sends.
|
||||
## This setting applies globally to all users.
|
||||
## To control this on a per-org basis instead, use the "Disable Send" org policy.
|
||||
# SENDS_ALLOWED=true
|
||||
|
||||
## HIBP Api Key
|
||||
## HaveIBeenPwned API Key, request it here: https://haveibeenpwned.com/API/Key
|
||||
# HIBP_API_KEY=
|
||||
|
||||
## Per-organization attachment storage limit (KB)
|
||||
## Max kilobytes of attachment storage allowed per organization.
|
||||
## When this limit is reached, organization members will not be allowed to upload further attachments for ciphers owned by that organization.
|
||||
# ORG_ATTACHMENT_LIMIT=
|
||||
## Per-user attachment storage limit (KB)
|
||||
## Max kilobytes of attachment storage allowed per user.
|
||||
## When this limit is reached, the user will not be allowed to upload further attachments.
|
||||
# USER_ATTACHMENT_LIMIT=
|
||||
## Per-user send storage limit (KB)
|
||||
## Max kilobytes of send storage allowed per user.
|
||||
## When this limit is reached, the user will not be allowed to upload further sends.
|
||||
# USER_SEND_LIMIT=
|
||||
|
||||
## Number of days to wait before auto-deleting a trashed item.
|
||||
## If unset (the default), trashed items are not auto-deleted.
|
||||
## This setting applies globally, so make sure to inform all users of any changes to this setting.
|
||||
# TRASH_AUTO_DELETE_DAYS=
|
||||
|
||||
## Number of minutes to wait before a 2FA-enabled login is considered incomplete,
|
||||
## resulting in an email notification. An incomplete 2FA login is one where the correct
|
||||
## master password was provided but the required 2FA step was not completed, which
|
||||
## potentially indicates a master password compromise. Set to 0 to disable this check.
|
||||
## This setting applies globally to all users.
|
||||
# INCOMPLETE_2FA_TIME_LIMIT=3
|
||||
|
||||
## Disable icon downloading
|
||||
## Set to true to disable icon downloading in the internal icon service.
|
||||
## This still serves existing icons from $ICON_CACHE_FOLDER, without generating any external
|
||||
## network requests. $ICON_CACHE_TTL must also be set to 0; otherwise, the existing icons
|
||||
## will be deleted eventually, but won't be downloaded again.
|
||||
# DISABLE_ICON_DOWNLOAD=false
|
||||
|
||||
## Controls if new users can register
|
||||
SIGNUPS_ALLOWED = "false";
|
||||
|
||||
## Controls if new users need to verify their email address upon registration
|
||||
## Note that setting this option to true prevents logins until the email address has been verified!
|
||||
## The welcome email will include a verification link, and login attempts will periodically
|
||||
## trigger another verification email to be sent.
|
||||
SIGNUPS_VERIFY = "true";
|
||||
|
||||
## If SIGNUPS_VERIFY is set to true, this limits how many seconds after the last time
|
||||
## an email verification link has been sent another verification email will be sent
|
||||
# SIGNUPS_VERIFY_RESEND_TIME=3600
|
||||
|
||||
## If SIGNUPS_VERIFY is set to true, this limits how many times an email verification
|
||||
## email will be re-sent upon an attempted login.
|
||||
# SIGNUPS_VERIFY_RESEND_LIMIT=6
|
||||
|
||||
## Controls if new users from a list of comma-separated domains can register
|
||||
## even if SIGNUPS_ALLOWED is set to false
|
||||
# SIGNUPS_DOMAINS_WHITELIST=example.com,example.net,example.org
|
||||
|
||||
## Controls whether event logging is enabled for organizations
|
||||
## This setting applies to organizations.
|
||||
## Disabled by default. Also check the EVENT_CLEANUP_SCHEDULE and EVENTS_DAYS_RETAIN settings.
|
||||
# ORG_EVENTS_ENABLED=false
|
||||
|
||||
## Controls which users can create new orgs.
|
||||
## Blank or 'all' means all users can create orgs (this is the default):
|
||||
# ORG_CREATION_USERS=
|
||||
## 'none' means no users can create orgs:
|
||||
# ORG_CREATION_USERS=none
|
||||
## A comma-separated list means only those users can create orgs:
|
||||
# ORG_CREATION_USERS=admin1@example.com,admin2@example.com
|
||||
|
||||
## Invitations org admins to invite users, even when signups are disabled
|
||||
# INVITATIONS_ALLOWED=true
|
||||
## Name shown in the invitation emails that don't come from a specific organization
|
||||
INVITATION_ORG_NAME = "Hugo's Vault";
|
||||
|
||||
## The number of hours after which an organization invite token, emergency access invite token,
|
||||
## email verification token and deletion request token will expire (must be at least 1)
|
||||
# INVITATION_EXPIRATION_HOURS=120
|
||||
|
||||
## Controls whether users can enable emergency access to their accounts.
|
||||
## This setting applies globally to all users.
|
||||
# EMERGENCY_ACCESS_ALLOWED=true
|
||||
|
||||
## Controls whether users can change their email.
|
||||
## This setting applies globally to all users
|
||||
# EMAIL_CHANGE_ALLOWED=true
|
||||
|
||||
## Number of server-side passwords hashing iterations for the password hash.
|
||||
## The default for new users. If changed, it will be updated during login for existing users.
|
||||
# PASSWORD_ITERATIONS=600000
|
||||
|
||||
## Controls whether users can set password hints. This setting applies globally to all users.
|
||||
# PASSWORD_HINTS_ALLOWED=true
|
||||
|
||||
## Controls whether a password hint should be shown directly in the web page if
|
||||
## SMTP service is not configured. Not recommended for publicly-accessible instances
|
||||
## as this provides unauthenticated access to potentially sensitive data.
|
||||
SHOW_PASSWORD_HINT = "false";
|
||||
|
||||
#########################
|
||||
### Advanced settings ###
|
||||
#########################
|
||||
|
||||
## Client IP Header, used to identify the IP of the client, defaults to "X-Real-IP"
|
||||
## Set to the string "none" (without quotes), to disable any headers and just use the remote IP
|
||||
# IP_HEADER=X-Real-IP
|
||||
|
||||
## Icon service
|
||||
## The predefined icon services are: internal, bitwarden, duckduckgo, google.
|
||||
## To specify a custom icon service, set a URL template with exactly one instance of `{}`,
|
||||
## which is replaced with the domain. For example: `https://icon.example.com/domain/{}`.
|
||||
##
|
||||
## `internal` refers to Vaultwarden's built-in icon fetching implementation.
|
||||
## If an external service is set, an icon request to Vaultwarden will return an HTTP
|
||||
## redirect to the corresponding icon at the external service. An external service may
|
||||
## be useful if your Vaultwarden instance has no external network connectivity, or if
|
||||
## you are concerned that someone may probe your instance to try to detect whether icons
|
||||
## for certain sites have been cached.
|
||||
# ICON_SERVICE=internal
|
||||
|
||||
## Icon redirect code
|
||||
## The HTTP status code to use for redirects to an external icon service.
|
||||
## The supported codes are 301 (legacy permanent), 302 (legacy temporary), 307 (temporary), and 308 (permanent).
|
||||
## Temporary redirects are useful while testing different icon services, but once a service
|
||||
## has been decided on, consider using permanent redirects for cacheability. The legacy codes
|
||||
## are currently better supported by the Bitwarden clients.
|
||||
# ICON_REDIRECT_CODE=302
|
||||
|
||||
## Cache time-to-live for successfully obtained icons, in seconds (0 is "forever")
|
||||
## Default: 2592000 (30 days)
|
||||
# ICON_CACHE_TTL=2592000
|
||||
## Cache time-to-live for icons which weren't available, in seconds (0 is "forever")
|
||||
## Default: 2592000 (3 days)
|
||||
# ICON_CACHE_NEGTTL=259200
|
||||
|
||||
## Icon download timeout
|
||||
## Configure the timeout value when downloading the favicons.
|
||||
## The default is 10 seconds, but this could be to low on slower network connections
|
||||
# ICON_DOWNLOAD_TIMEOUT=10
|
||||
|
||||
## Block HTTP domains/IPs by Regex
|
||||
## Any domains or IPs that match this regex won't be fetched by the internal HTTP client.
|
||||
## Useful to hide other servers in the local network. Check the WIKI for more details
|
||||
## NOTE: Always enclose this regex withing single quotes!
|
||||
# HTTP_REQUEST_BLOCK_REGEX='^(192\.168\.0\.[0-9]+|192\.168\.1\.[0-9]+)$'
|
||||
|
||||
## Enabling this will cause the internal HTTP client to refuse to connect to any non global IP address.
|
||||
## Useful to secure your internal environment: See https://en.wikipedia.org/wiki/Reserved_IP_addresses for a list of IPs which it will block
|
||||
# HTTP_REQUEST_BLOCK_NON_GLOBAL_IPS=true
|
||||
|
||||
## Client Settings
|
||||
## Enable experimental feature flags for clients.
|
||||
## This is a comma-separated list of flags, e.g. "flag1,flag2,flag3".
|
||||
##
|
||||
## The following flags are available:
|
||||
## - "autofill-overlay": Add an overlay menu to form fields for quick access to credentials.
|
||||
## - "autofill-v2": Use the new autofill implementation.
|
||||
## - "browser-fileless-import": Directly import credentials from other providers without a file.
|
||||
## - "fido2-vault-credentials": Enable the use of FIDO2 security keys as second factor.
|
||||
# EXPERIMENTAL_CLIENT_FEATURE_FLAGS=fido2-vault-credentials
|
||||
|
||||
## Require new device emails. When a user logs in an email is required to be sent.
|
||||
## If sending the email fails the login attempt will fail!!
|
||||
# REQUIRE_DEVICE_EMAIL=false
|
||||
|
||||
## Enable extended logging, which shows timestamps and targets in the logs
|
||||
# EXTENDED_LOGGING=true
|
||||
|
||||
## Timestamp format used in extended logging.
|
||||
## Format specifiers: https://docs.rs/chrono/latest/chrono/format/strftime
|
||||
# LOG_TIMESTAMP_FORMAT="%Y-%m-%d %H:%M:%S.%3f"
|
||||
|
||||
## Logging to Syslog
|
||||
## This requires extended logging
|
||||
# USE_SYSLOG=false
|
||||
|
||||
## Logging to file
|
||||
# LOG_FILE=/path/to/log
|
||||
|
||||
## Log level
|
||||
## Change the verbosity of the log output
|
||||
## Valid values are "trace", "debug", "info", "warn", "error" and "off"
|
||||
## Setting it to "trace" or "debug" would also show logs for mounted routes and static file, websocket and alive requests
|
||||
## For a specific module append a comma separated `path::to::module=log_level`
|
||||
## For example, to only see debug logs for icons use: LOG_LEVEL="info,vaultwarden::api::icons=debug"
|
||||
LOG_LEVEL = "warn";
|
||||
|
||||
## Token for the admin interface, preferably an Argon2 PCH string
|
||||
## Vaultwarden has a built-in generator by calling `vaultwarden hash`
|
||||
## For details see: https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page#secure-the-admin_token
|
||||
## If not set, the admin panel is disabled
|
||||
## New Argon2 PHC string
|
||||
## Note that for some environments, like docker-compose you need to escape all the dollar signs `$` with an extra dollar sign like `$$`
|
||||
## Also, use single quotes (') instead of double quotes (") to enclose the string when needed
|
||||
# ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$MmeKRnGK5RW5mJS7h3TOL89GrpLPXJPAtTK8FTqj9HM$DqsstvoSAETl9YhnsXbf43WeaUwJC6JhViIvuPoig78'
|
||||
## Old plain text string (Will generate warnings in favor of Argon2)
|
||||
# ADMIN_TOKEN=Vy2VyYTTsKPv8W5aEOWUbB/Bt3DEKePbHmI4m9VcemUMS2rEviDowNAFqYi1xjmp
|
||||
|
||||
## Enable this to bypass the admin panel security. This option is only
|
||||
## meant to be used with the use of a separate auth layer in front
|
||||
# DISABLE_ADMIN_TOKEN=false
|
||||
|
||||
## Number of seconds, on average, between admin login requests from the same IP address before rate limiting kicks in.
|
||||
# ADMIN_RATELIMIT_SECONDS=300
|
||||
## Allow a burst of requests of up to this size, while maintaining the average indicated by `ADMIN_RATELIMIT_SECONDS`.
|
||||
# ADMIN_RATELIMIT_MAX_BURST=3
|
||||
|
||||
## Set the lifetime of admin sessions to this value (in minutes).
|
||||
# ADMIN_SESSION_LIFETIME=20
|
||||
|
||||
## Allowed iframe ancestors (Know the risks!)
|
||||
## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
|
||||
## Allows other domains to embed the web vault into an iframe, useful for embedding into secure intranets
|
||||
## This adds the configured value to the 'Content-Security-Policy' headers 'frame-ancestors' value.
|
||||
## Multiple values must be separated with a whitespace.
|
||||
# ALLOWED_IFRAME_ANCESTORS=
|
||||
|
||||
## Number of seconds, on average, between login requests from the same IP address before rate limiting kicks in.
|
||||
# LOGIN_RATELIMIT_SECONDS=60
|
||||
## Allow a burst of requests of up to this size, while maintaining the average indicated by `LOGIN_RATELIMIT_SECONDS`.
|
||||
## Note that this applies to both the login and the 2FA, so it's recommended to allow a burst size of at least 2.
|
||||
# LOGIN_RATELIMIT_MAX_BURST=10
|
||||
|
||||
## BETA FEATURE: Groups
|
||||
## Controls whether group support is enabled for organizations
|
||||
## This setting applies to organizations.
|
||||
## Disabled by default because this is a beta feature, it contains known issues!
|
||||
## KNOW WHAT YOU ARE DOING!
|
||||
# ORG_GROUPS_ENABLED=false
|
||||
|
||||
## Increase secure note size limit (Know the risks!)
|
||||
## Sets the secure note size limit to 100_000 instead of the default 10_000.
|
||||
## WARNING: This could cause issues with clients. Also exports will not work on Bitwarden servers!
|
||||
## KNOW WHAT YOU ARE DOING!
|
||||
# INCREASE_NOTE_SIZE_LIMIT=false
|
||||
|
||||
## Enforce Single Org with Reset Password Policy
|
||||
## Enforce that the Single Org policy is enabled before setting the Reset Password policy
|
||||
## Bitwarden enforces this by default. In Vaultwarden we encouraged to use multiple organizations because groups were not available.
|
||||
## Setting this to true will enforce the Single Org Policy to be enabled before you can enable the Reset Password policy.
|
||||
# ENFORCE_SINGLE_ORG_WITH_RESET_PW_POLICY=false
|
||||
|
||||
########################
|
||||
### MFA/2FA settings ###
|
||||
########################
|
||||
|
||||
## Yubico (Yubikey) Settings
|
||||
## Set your Client ID and Secret Key for Yubikey OTP
|
||||
## You can generate it here: https://upgrade.yubico.com/getapikey/
|
||||
## You can optionally specify a custom OTP server
|
||||
# YUBICO_CLIENT_ID=11111
|
||||
# YUBICO_SECRET_KEY=AAAAAAAAAAAAAAAAAAAAAAAA
|
||||
# YUBICO_SERVER=http://yourdomain.com/wsapi/2.0/verify
|
||||
|
||||
## Duo Settings
|
||||
## You need to configure the DUO_IKEY, DUO_SKEY, and DUO_HOST options to enable global Duo support.
|
||||
## Otherwise users will need to configure it themselves.
|
||||
## Create an account and protect an application as mentioned in this link (only the first step, not the rest):
|
||||
## https://help.bitwarden.com/article/setup-two-step-login-duo/#create-a-duo-security-account
|
||||
## Then set the following options, based on the values obtained from the last step:
|
||||
# DUO_IKEY=<Client ID>
|
||||
# DUO_SKEY=<Client Secret>
|
||||
# DUO_HOST=<API Hostname>
|
||||
## After that, you should be able to follow the rest of the guide linked above,
|
||||
## ignoring the fields that ask for the values that you already configured beforehand.
|
||||
##
|
||||
## If you want to attempt to use Duo's 'Traditional Prompt' (deprecated, iframe based) set DUO_USE_IFRAME to 'true'.
|
||||
## Duo no longer supports this, but it still works for some integrations.
|
||||
## If you aren't sure, leave this alone.
|
||||
# DUO_USE_IFRAME=false
|
||||
|
||||
## Email 2FA settings
|
||||
## Email token size
|
||||
## Number of digits in an email 2FA token (min: 6, max: 255).
|
||||
## Note that the Bitwarden clients are hardcoded to mention 6 digit codes regardless of this setting!
|
||||
# EMAIL_TOKEN_SIZE=6
|
||||
##
|
||||
## Token expiration time
|
||||
## Maximum time in seconds a token is valid. The time the user has to open email client and copy token.
|
||||
# EMAIL_EXPIRATION_TIME=600
|
||||
##
|
||||
## Maximum attempts before an email token is reset and a new email will need to be sent.
|
||||
# EMAIL_ATTEMPTS_LIMIT=3
|
||||
##
|
||||
## Setup email 2FA regardless of any organization policy
|
||||
# EMAIL_2FA_ENFORCE_ON_VERIFIED_INVITE=false
|
||||
## Automatically setup email 2FA as fallback provider when needed
|
||||
# EMAIL_2FA_AUTO_FALLBACK=false
|
||||
|
||||
## Other MFA/2FA settings
|
||||
## Disable 2FA remember
|
||||
## Enabling this would force the users to use a second factor to login every time.
|
||||
## Note that the checkbox would still be present, but ignored.
|
||||
# DISABLE_2FA_REMEMBER=false
|
||||
##
|
||||
## Authenticator Settings
|
||||
## Disable authenticator time drifted codes to be valid.
|
||||
## TOTP codes of the previous and next 30 seconds will be invalid
|
||||
##
|
||||
## According to the RFC6238 (https://tools.ietf.org/html/rfc6238),
|
||||
## we allow by default the TOTP code which was valid one step back and one in the future.
|
||||
## This can however allow attackers to be a bit more lucky with there attempts because there are 3 valid codes.
|
||||
## You can disable this, so that only the current TOTP Code is allowed.
|
||||
## Keep in mind that when a sever drifts out of time, valid codes could be marked as invalid.
|
||||
## In any case, if a code has been used it can not be used again, also codes which predates it will be invalid.
|
||||
# AUTHENTICATOR_DISABLE_TIME_DRIFT=false
|
||||
|
||||
###########################
|
||||
### SMTP Email settings ###
|
||||
###########################
|
||||
|
||||
## Mail specific settings, set SMTP_FROM and either SMTP_HOST or USE_SENDMAIL to enable the mail service.
|
||||
## To make sure the email links are pointing to the correct host, set the DOMAIN variable.
|
||||
## Note: if SMTP_USERNAME is specified, SMTP_PASSWORD is mandatory
|
||||
SMTP_HOST = "smtp.gmail.com";
|
||||
SMTP_FROM = "vault@depeuter.dev";
|
||||
SMTP_FROM_NAME = "Hugo's Vault";
|
||||
# SMTP_USERNAME=username
|
||||
# SMTP_PASSWORD=password
|
||||
# SMTP_TIMEOUT=15
|
||||
|
||||
## Choose the type of secure connection for SMTP. The default is "starttls".
|
||||
## The available options are:
|
||||
## - "starttls": The default port is 587.
|
||||
## - "force_tls": The default port is 465.
|
||||
## - "off": The default port is 25.
|
||||
## Ports 587 (submission) and 25 (smtp) are standard without encryption and with encryption via STARTTLS (Explicit TLS). Port 465 (submissions) is used for encrypted submission (Implicit TLS).
|
||||
SMTP_SECURITY = "starttls";
|
||||
SMTP_PORT = "587";
|
||||
|
||||
# Whether to send mail via the `sendmail` command
|
||||
# USE_SENDMAIL=false
|
||||
# Which sendmail command to use. The one found in the $PATH is used if not specified.
|
||||
# SENDMAIL_COMMAND="/path/to/sendmail"
|
||||
|
||||
## Defaults for SSL is "Plain" and "Login" and nothing for Non-SSL connections.
|
||||
## Possible values: ["Plain", "Login", "Xoauth2"].
|
||||
## Multiple options need to be separated by a comma ','.
|
||||
SMTP_AUTH_MECHANISM = "Login";
|
||||
|
||||
## Server name sent during the SMTP HELO
|
||||
## By default this value should be is on the machine's hostname,
|
||||
## but might need to be changed in case it trips some anti-spam filters
|
||||
# HELO_NAME=
|
||||
|
||||
## Embed images as email attachments
|
||||
# SMTP_EMBED_IMAGES=true
|
||||
|
||||
## SMTP debugging
|
||||
## When set to true this will output very detailed SMTP messages.
|
||||
## WARNING: This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting!
|
||||
# SMTP_DEBUG=false
|
||||
|
||||
## Accept Invalid Certificates
|
||||
## DANGEROUS: This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
||||
## Only use this as a last resort if you are not able to use a valid certificate.
|
||||
## If the Certificate is valid but the hostname doesn't match, please use SMTP_ACCEPT_INVALID_HOSTNAMES instead.
|
||||
# SMTP_ACCEPT_INVALID_CERTS=false
|
||||
|
||||
## Accept Invalid Hostnames
|
||||
## DANGEROUS: This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
||||
## Only use this as a last resort if you are not able to use a valid certificate.
|
||||
# SMTP_ACCEPT_INVALID_HOSTNAMES=false
|
||||
|
||||
#######################
|
||||
### Rocket settings ###
|
||||
#######################
|
||||
|
||||
## Rocket specific settings
|
||||
## See https://rocket.rs/v0.5/guide/configuration/ for more details.
|
||||
# ROCKET_ADDRESS=0.0.0.0
|
||||
## The default port is 8000, unless running in a Docker container, in which case it is 80.
|
||||
# ROCKET_PORT=8000
|
||||
# ROCKET_TLS={certs="/path/to/certs.pem",key="/path/to/key.pem"}
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
16
modules/common/default.nix
Normal file
16
modules/common/default.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
config = {
|
||||
homelab = {
|
||||
services.openssh.enable = true;
|
||||
users.admin.enable = true;
|
||||
};
|
||||
|
||||
nix.settings.experimental-features = [
|
||||
"flakes"
|
||||
"nix-command"
|
||||
];
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "Europe/Brussels";
|
||||
};
|
||||
}
|
||||
9
modules/default.nix
Normal file
9
modules/default.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
imports = [
|
||||
./apps
|
||||
./services
|
||||
./virtualisation
|
||||
|
||||
./common
|
||||
];
|
||||
}
|
||||
49
modules/services/actions/default.nix
Normal file
49
modules/services/actions/default.nix
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.services.actions;
|
||||
in {
|
||||
options.homelab.services.actions.enable = lib.mkEnableOption "Actions runner";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
homelab.virtualisation.containers.enable = true;
|
||||
|
||||
services.gitea-actions-runner = {
|
||||
instances.depeuter-dev = {
|
||||
enable = true;
|
||||
url = "https://git.depeuter.dev";
|
||||
tokenFile = "/etc/runner/depeuter-dev";
|
||||
name = config.networking.hostName;
|
||||
labels = [
|
||||
"debian-11:docker://debian:11"
|
||||
"debian-12:docker://debian:12"
|
||||
"debian-latest:docker://debian:latest"
|
||||
"docker:host"
|
||||
"Linux:host"
|
||||
"self-hosted:host"
|
||||
"ubuntu-22.04:docker://ubuntu:22.04"
|
||||
"ubuntu-24.04:docker://ubuntu:24.04"
|
||||
"ubuntu-latest:docker://ubuntu:latest"
|
||||
];
|
||||
settings = {
|
||||
cache.enabled = true;
|
||||
container.privileged = true;
|
||||
};
|
||||
hostPackages = with pkgs; [
|
||||
bash
|
||||
cmake
|
||||
coreutils
|
||||
curl
|
||||
docker
|
||||
gawk
|
||||
git
|
||||
gnused
|
||||
nodejs
|
||||
openssh
|
||||
wget
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
6
modules/services/default.nix
Normal file
6
modules/services/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./actions
|
||||
./openssh
|
||||
];
|
||||
}
|
||||
20
modules/services/openssh/default.nix
Normal file
20
modules/services/openssh/default.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.services.openssh;
|
||||
in {
|
||||
options.homelab.services.openssh.enable = lib.mkEnableOption "OpenSSH daemon";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.openssh = {
|
||||
# Enable the OpenSSH daemon.
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
# Disable keyboard-interactive authentication.
|
||||
KbdInteractiveAuthentication = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
23
modules/virtualisation/containers/default.nix
Normal file
23
modules/virtualisation/containers/default.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.virtualisation.containers;
|
||||
in {
|
||||
options.homelab.virtualisation.containers.enable = lib.mkEnableOption "OCI containers";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
nfs-utils
|
||||
];
|
||||
|
||||
virtualisation = {
|
||||
docker = {
|
||||
enable = true;
|
||||
enableOnBoot = true;
|
||||
autoPrune.enable = true;
|
||||
};
|
||||
|
||||
oci-containers.backend = "docker";
|
||||
};
|
||||
};
|
||||
}
|
||||
6
modules/virtualisation/default.nix
Normal file
6
modules/virtualisation/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./containers
|
||||
./guest
|
||||
];
|
||||
}
|
||||
34
modules/virtualisation/guest/default.nix
Normal file
34
modules/virtualisation/guest/default.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{ config, lib, modulesPath, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.virtualisation.guest;
|
||||
in {
|
||||
options.homelab.virtualisation.guest.enable = lib.mkEnableOption "Settings for devices running on virtualisation, e.g. Proxmox";
|
||||
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
boot = {
|
||||
# Whether to enable growing the root partition on boot.
|
||||
growPartition = true;
|
||||
# Use Grub bootloader
|
||||
loader.grub = {
|
||||
enable = true;
|
||||
devices = [
|
||||
"nodev"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems."/" = lib.mkDefault {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
autoResize = true;
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
# Enable QEMU Guest for Proxmox
|
||||
services.qemuGuest.enable = true;
|
||||
};
|
||||
}
|
||||
33
users/admin/default.nix
Normal file
33
users/admin/default.nix
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.users.admin;
|
||||
in {
|
||||
options.homelab.users.admin.enable = lib.mkEnableOption "user System Administrator";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
nix.settings.trusted-users = [
|
||||
config.users.users.admin.name
|
||||
];
|
||||
|
||||
users.users.admin = {
|
||||
description = "System Administrator";
|
||||
isNormalUser = true;
|
||||
extraGroups = [
|
||||
config.users.groups.wheel.name # Enable 'sudo' for the user.
|
||||
];
|
||||
initialPassword = "ChangeMe";
|
||||
openssh.authorizedKeys.keys = [
|
||||
# TODO ChangeMe
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPrG+ldRBdCeHEXrsy/qHXIJYg8xQXVuiUR0DxhFjYNg"
|
||||
];
|
||||
packages = with pkgs; [
|
||||
curl
|
||||
git
|
||||
tmux
|
||||
vim
|
||||
wget
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
18
users/apps/default.nix
Normal file
18
users/apps/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.users.apps;
|
||||
in {
|
||||
options.homelab.users.apps.enable = lib.mkEnableOption "user Apps";
|
||||
|
||||
config.users = lib.mkIf cfg.enable {
|
||||
groups.apps.gid = lib.mkForce 568;
|
||||
users.apps = {
|
||||
uid = lib.mkForce 568;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.apps.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
};
|
||||
}
|
||||
26
users/backup/default.nix
Normal file
26
users/backup/default.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.users.backup;
|
||||
in {
|
||||
options.homelab.users.backup.enable = lib.mkEnableOption "user Backup";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users.backup = {
|
||||
description = "Backup User";
|
||||
isNormalUser = true;
|
||||
extraGroups = [
|
||||
"docker" # Allow access to the docker socket.
|
||||
];
|
||||
openssh.authorizedKeys.keys = [
|
||||
# TODO ChangeMe
|
||||
|
||||
# Tibo-NixFat
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPrG+ldRBdCeHEXrsy/qHXIJYg8xQXVuiUR0DxhFjYNg"
|
||||
|
||||
# Hugo
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAxR813vqq5zbu1NHrIybu5Imlu3k0rDCGxHiuGEhPoVV9c5FpnKNGLCi3ctm15ZcVBX4HcponYsKRBsCzM2pI4uXjxhHkLzbss5LttFuSzv5v/QHfLW1bvyJEMBEPxguGqAydAeWrBFdI9uHBEXeb325uKxMKBZHYvvpyAQ115c1wKy1bL8BfR0LTkhsFqexRvI86q59AVrAU/KFf6RXO0T9QA6H/vyWLlIPc7Ta+tSWwQ68bMmS5Pwn8q58tOAOAd6Lpt4TqUDJSppPjLEPKyKC6ShwMdEjwmwpEG0hxfsvaU8XERyQbSbEE9sLHRA2LoEdtMx3J8nzX3AwYUNspsqIv6NQZksnVqJ8OfL45ngUFcSJ6kBsUvCZfzEUGUTJ6Js0v84NOIXxNG/ZfPsk6ArXm3dvj2TYeK8llO6wpJnMMyztmmiODWoj9tepZSij44IgVM5wdWYIK/RZoYTsCQbmvJFfB8jhyJnf/7F19Vo5+LwhmCOsQh/KEK0F1DVc= admin@Hugo"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
9
users/default.nix
Normal file
9
users/default.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
imports = [
|
||||
./admin
|
||||
./apps
|
||||
./backup
|
||||
./deploy
|
||||
./media
|
||||
];
|
||||
}
|
||||
49
users/deploy/default.nix
Normal file
49
users/deploy/default.nix
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.users.deploy;
|
||||
in {
|
||||
options.homelab.users.deploy.enable = lib.mkEnableOption "user Deploy";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users = {
|
||||
groups.deploy = { };
|
||||
|
||||
# The user used to deploy rebuilds without password authentication
|
||||
users.deploy = {
|
||||
group = config.users.groups.deploy.name;
|
||||
isSystemUser = true;
|
||||
home = "/var/empty";
|
||||
shell = pkgs.bashInteractive;
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPrG+ldRBdCeHEXrsy/qHXIJYg8xQXVuiUR0DxhFjYNg"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
security.sudo.extraRules = [
|
||||
{
|
||||
groups = [
|
||||
config.users.groups.deploy.name
|
||||
];
|
||||
commands = [
|
||||
{
|
||||
command = "/nix/store/*-nix-*/bin/nix-env -p /nix/var/nix/profile/system --set /nix/store/*-*";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
groups = [
|
||||
config.users.groups.deploy.name
|
||||
];
|
||||
commands = [
|
||||
{
|
||||
command = "/nix/store/*/bin/switch-to-configuration";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
18
users/media/default.nix
Normal file
18
users/media/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.homelab.users.media;
|
||||
in {
|
||||
options.homelab.users.media.enable = lib.mkEnableOption "user Media";
|
||||
|
||||
config.users = lib.mkIf cfg.enable {
|
||||
groups.media.gid = lib.mkForce 3000;
|
||||
users.media = {
|
||||
uid = lib.mkForce 3001;
|
||||
isSystemUser = true;
|
||||
group = config.users.groups.media.name;
|
||||
home = "/var/empty";
|
||||
shell = null;
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue