Added copyparty+samba module, updated traefik
This commit is contained in:
+27
-3
@@ -40,6 +40,7 @@ This guide documents the process for a minimal installation of NixOS on a Proxmo
|
||||
- [[#step-2-updating-sops-and-re-encrypting-secrets][Step 2: Updating SOPS and Re-encrypting Secrets]]
|
||||
- [[#optional-nixos-modules][Optional NixOS Modules]]
|
||||
- [[#reverse-proxies][Reverse Proxies]]
|
||||
- [[#file-servers][File Servers]]
|
||||
- [[#notes-and-configuration-details][Notes and Configuration Details]]
|
||||
- [[#disko-configuration-for-proxmox-mbr-boot][Disko Configuration for Proxmox (MBR Boot)]]
|
||||
- [[#generating-hardware-configuration][Generating Hardware Configuration]]
|
||||
@@ -114,7 +115,7 @@ The new AGE key must be added to your =.sops.yaml= configuration file. This allo
|
||||
** Reverse Proxies
|
||||
The following modules can be enabled to provide a reverse proxy.
|
||||
|
||||
*Note:* Currently, none of the available reverse proxy modules (NGINX, Traefik, Caddy) are functional. This is a known issue that needs to be investigated.
|
||||
*Note:* Previously, all reverse proxy modules were considered non-functional. Recent troubleshooting has provided a fix for Traefik, but the other modules may still have issues.
|
||||
|
||||
*** NGINX
|
||||
The initial switch to this configuration may be slow as it waits for ACME to issue SSL certificates.
|
||||
@@ -128,7 +129,6 @@ dov = {
|
||||
#+end_src
|
||||
|
||||
*** Traefik
|
||||
This module is currently considered to be in a broken state.
|
||||
#+begin_src nix
|
||||
dov = {
|
||||
# Reverse Proxy
|
||||
@@ -138,6 +138,14 @@ dov = {
|
||||
};
|
||||
#+end_src
|
||||
|
||||
**** Troubleshooting Traefik ACME with DuckDNS
|
||||
- *Context:* Issues getting an ACME certificate from DuckDNS with Traefik.
|
||||
- *Roadblock:* The process was failing, but eventually succeeded.
|
||||
- *Possible Solutions:*
|
||||
- Setting =disablePropagationCheck = true;= for the DNS challenge.
|
||||
- Extending the =delay= for the DNS challenge.
|
||||
- *Notes:* It's unclear which specific option resolved the issue, but one of them, or a combination, allowed the certificate to be obtained. The first time Traefik tries to get a certificate it might fail, and a restart of the service is needed. After some time, the Let's Encrypt certificate will be received.
|
||||
|
||||
*** Caddy
|
||||
#+begin_src nix
|
||||
dov = {
|
||||
@@ -148,6 +156,22 @@ dov = {
|
||||
};
|
||||
#+end_src
|
||||
|
||||
** File Servers
|
||||
*** copyparty
|
||||
Provides a web-based file manager.
|
||||
#+begin_src nix
|
||||
dov = {
|
||||
file-server.copyparty.enable = true;
|
||||
};
|
||||
#+end_src
|
||||
|
||||
*Dependency:* For =copyparty= to function correctly in this configuration, it requires a Samba share to be mounted to the path =/MEDIA=. Therefore, the =samba= module must also be enabled:
|
||||
#+begin_src nix
|
||||
dov = {
|
||||
samba.enable = true;
|
||||
};
|
||||
#+end_src
|
||||
|
||||
* Notes and Configuration Details
|
||||
** Disko Configuration for Proxmox (MBR Boot)
|
||||
A critical requirement for ensuring a NixOS VM can boot correctly in Proxmox is the disk partition scheme. Proxmox expects a Master Boot Record (MBR) compatible setup.
|
||||
@@ -194,7 +218,7 @@ nix run github:nix-community/nixos-anywhere -- \
|
||||
#+end_src
|
||||
|
||||
* TODOs
|
||||
- [ ] Investigate and fix the issue preventing any of the reverse proxy modules (NGINX, Traefik, Caddy) from working correctly.
|
||||
- [ ] Investigate and fix remaining issues with reverse proxy modules (NGINX, Caddy).
|
||||
- [ ] Troubleshoot and fix an issue that occurs when reloading the NixOS configuration remotely, which breaks the SSH pipe and requires entering the root password three times.
|
||||
- [ ] Investigate and resolve the issue where updating a user's password declaratively using a secret managed by =sops= failed after the initial installation.
|
||||
- [ ] Refactor the =disko= configuration to make the disk device name (e.g., =/dev/sda=) a variable. This will avoid hardcoding the value and make the configuration more portable.
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
disko.nixosModules.disko
|
||||
home-manager.nixosModules.home-manager
|
||||
sops-nix.nixosModules.sops
|
||||
inputs.copyparty.nixosModules.default
|
||||
|
||||
./main
|
||||
./modules
|
||||
|
||||
+4
-2
@@ -137,7 +137,7 @@ in {
|
||||
# Reverse Proxy
|
||||
reverse-proxy = {
|
||||
nginx.enable = false; # TODO does not work for some reason
|
||||
traefik.enable = true; # TODO has issues retrieving certificate from duckdns
|
||||
traefik.enable = true;
|
||||
caddy.enable = false; # TODO has issues retrieving certificate from duckdns
|
||||
};
|
||||
|
||||
@@ -148,7 +148,9 @@ in {
|
||||
|
||||
social.matrix.enable = false; # TODO does not work :)
|
||||
|
||||
file-server.copyparty.enable = false;
|
||||
file-server.copyparty.enable = true;
|
||||
|
||||
samba.enable = true;
|
||||
};
|
||||
|
||||
# DO NOT CHANGE AT ANY POINT!
|
||||
|
||||
@@ -11,6 +11,10 @@ example_booleans:
|
||||
user_password: ENC[AES256_GCM,data:Q7rk67ylyjr5Sa+AYCxnQAPLbBP5Fy85wTGLZuqxBG3iJ+MmhEgfeatVA2tcsY7GSaU/vghny+TJtrvhDYYMqa10h/F0wPxUjId78qkhKbnRQs4mqAxA9heSi4ojp1kh/pXN7tj64wNyJA==,iv:FTUojVNz78tn/Uj1N8Oj5Iov9eEMRo5vz+mqHdewxjg=,tag:YF74hLXXUby0IjHrqdkBUQ==,type:str]
|
||||
duckdns-token: ENC[AES256_GCM,data:Gf3kIpOO/X+ZVXV4w71Fp5qMuNedBBoobazAFpp22RC70xKb6xsJVffWdtFq0blDe5Y=,iv:SNq6wnhG6CuDwB3NQ/PryTgY3U/J2g1XfGCW7gSEYbo=,tag:MWqhrJRreGZ/SaapAaCXQA==,type:str]
|
||||
matrix_secret: ENC[AES256_GCM,data:U1yPFsFeLA5tbFf/MMACrhmH/32zUMUg2HOHWdAtcm+ybg9KgjhQmbGDM/MTDoRaAa+Zqfs774gz3A6Rg4HLuvCr4cPotSCHH8qRPz+UDK4Bvf305EfLP22Rrhc=,iv:A9BSgw1hHg+y8x4GC4hWNBCaYZNlRfS1+jKKv38znXg=,tag:SkwEfez7TRhFuLEL4PkvZA==,type:str]
|
||||
copyparty:
|
||||
admin_password: ENC[AES256_GCM,data:VlHcQB1Z1/wSUi8yCEpcW+i8h3c=,iv:mystE6THTS50LzV/TPm+QtZ1C87Vxtx+W9jVzcGAnSM=,tag:8nxtbklHwJnI7VHjJA55dQ==,type:str]
|
||||
alex_password: ENC[AES256_GCM,data:0X5AZH8tqJRd6er5w3oMaWI0jrE=,iv:/2aLquP4LVCKCozJsMGItqX9+L9pxSM4PRpn6QnDzbE=,tag:b1GRHEBwQNYBtERj1xqjoA==,type:str]
|
||||
smb-secrets: ENC[AES256_GCM,data:RW8xaGU94jxE/iTocH3ylCP5uIpmnSg/MQDC+e5i9PhvlsNY+kfUiqQHoDXETgEPmNUbLr2qZSMLPhQ=,iv:5vkw0Qfa7UHYZ2ODOvFZgirehpY7muV6fvjWHAyHMu4=,tag:cuEzibaBZVf5HVlAF2xUIA==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age19wvqtn4ju6k4vs8fxr34unl6xx4cv04jw0lx9ps20xlde927zfssgl4qke
|
||||
@@ -31,7 +35,7 @@ sops:
|
||||
NHdWQnlGbk43WS80VDkxV0o4TE5uSUUK0WSdFzR3u0pLUYHXaTMrtBm0sKKe9ZPG
|
||||
nF90b/jv66WGIH1n2oFaaohCkd7DZGzSpr0+KsqX6pkszYnp39YC5A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-07-26T21:14:39Z"
|
||||
mac: ENC[AES256_GCM,data:76/u+mXqsYQA0Y5rcUskN2Uh8nCKyZxPk3yLd4F/zXnfOe6eqLBAfwvZ2XGu1Y+KQEMidSvrd+7WJ9bPHFxbftglIIeU8NxdXqgQZrH2Bx6kMgGzSR72IzYOJvl5rPsYa3mjRIcaBdyE7oo3ZSQctHlf40zEaTNesNgjVPgvWhs=,iv:yYq5knPV7JdvnkC18/MFg1/6W1cx2d7zAtRCe/C2Txg=,tag:jc7grjZajT2TH3TzLVQ82Q==,type:str]
|
||||
lastmodified: "2025-07-27T18:42:07Z"
|
||||
mac: ENC[AES256_GCM,data:EP1ziiWZ3hPCbjLtPdLccL4csnNmLqtQkhwn8x5bwXuqIU9Q8U6+nXIorAG2Ck28hyjnAjHyYMbJcSSrNOVHroA5Xnlps65975WuKe3akNF6n6Nz+gTDQgEzIpxwYD2rEFNutCNN4EhESzh13lvsvdkxTCsFLjZzwQ4DSuVId24=,iv:f2jM71VXiShEkTUOtfONhMIeR6JnC3xpUN2zXJvdDLo=,tag:s62lb8GtrHHBj6ferphGog==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.10.2
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
./virtualisation
|
||||
./social
|
||||
./file-server
|
||||
./samba
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,19 +1,96 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, inputs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.dov.file-server.copyparty;
|
||||
let cfg = config.dov.file-server.copyparty;
|
||||
in {
|
||||
options.dov.file-server.copyparty = { enable = mkEnableOption "copyparty config"; };
|
||||
options.dov.file-server.copyparty = {
|
||||
enable = mkEnableOption "copyparty config";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# # add the copyparty overlay to expose the package to the module
|
||||
# nixpkgs.overlays = [ copyparty.overlays.default ];
|
||||
# # (optional) install the package globally
|
||||
# environment.systemPackages = [ pkgs.copyparty ];
|
||||
# # configure the copyparty module
|
||||
# services.copyparty.enable = cfg.enable;
|
||||
networking.firewall.allowedTCPPorts = config.services.copyparty.settings.p;
|
||||
|
||||
sops.secrets."copyparty/admin_password" = {
|
||||
owner = "copyparty";
|
||||
group = "copyparty";
|
||||
};
|
||||
sops.secrets."copyparty/alex_password" = {
|
||||
owner = "copyparty";
|
||||
group = "copyparty";
|
||||
};
|
||||
|
||||
# add the copyparty overlay to expose the package to the module
|
||||
nixpkgs.overlays = [ inputs.copyparty.overlays.default ];
|
||||
# (optional) install the package globally
|
||||
environment.systemPackages = [ pkgs.copyparty ];
|
||||
# configure the copyparty module
|
||||
services.copyparty = {
|
||||
enable = cfg.enable;
|
||||
settings = {
|
||||
p = [ 3923 ];
|
||||
e2dsa = true; # enable file indexing and filesystem scanning
|
||||
e2ts = true; # and enable multimedia indexing
|
||||
z = true; # and zeroconf
|
||||
qr = true; # and qrcode (you can comma-separate arguments)
|
||||
};
|
||||
accounts = {
|
||||
admin.passwordFile = "/run/secrets/copyparty/admin_password";
|
||||
alex.passwordFile = "/run/secrets/copyparty/alex_password";
|
||||
};
|
||||
|
||||
# create a volume
|
||||
volumes = {
|
||||
"/" = {
|
||||
# share the contents of "/MEDIA"
|
||||
path = "/";
|
||||
# see `copyparty --help-accounts` for available options
|
||||
access = {
|
||||
# everyone gets read-access, but
|
||||
r = [ "admin" "alex" ];
|
||||
# users "ed" and "k" get read-write
|
||||
rw = [ "admin" ];
|
||||
};
|
||||
# see `copyparty --help-flags` for available options
|
||||
flags = {
|
||||
# "fk" enables filekeys (necessary for upget permission) (4 chars long)
|
||||
fk = 4;
|
||||
# scan for new files every 60sec
|
||||
scan = 60;
|
||||
# volflag "e2d" enables the uploads database
|
||||
e2d = true;
|
||||
# "d2t" disables multimedia parsers (in case the uploads are malicious)
|
||||
d2t = true;
|
||||
# skips hashing file contents if path matches *.iso
|
||||
nohash = ".iso$";
|
||||
};
|
||||
};
|
||||
"/MEDIA" = {
|
||||
# share the contents of "/MEDIA"
|
||||
path = "/MEDIA";
|
||||
# see `copyparty --help-accounts` for available options
|
||||
access = {
|
||||
# everyone gets read-access, but
|
||||
r = "alex";
|
||||
# users "ed" and "k" get read-write
|
||||
rw = [ "admin" "alex" ];
|
||||
};
|
||||
# see `copyparty --help-flags` for available options
|
||||
flags = {
|
||||
# "fk" enables filekeys (necessary for upget permission) (4 chars long)
|
||||
fk = 4;
|
||||
# scan for new files every 60sec
|
||||
scan = 60;
|
||||
# volflag "e2d" enables the uploads database
|
||||
e2d = true;
|
||||
# "d2t" disables multimedia parsers (in case the uploads are malicious)
|
||||
d2t = true;
|
||||
# skips hashing file contents if path matches *.iso
|
||||
nohash = ".iso$";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ with lib;
|
||||
|
||||
let
|
||||
cfg = config.dov.reverse-proxy.traefik;
|
||||
domain = "susano-nixos.duckdns.org";
|
||||
configFile = pkgs.writeText "duckdns-options"
|
||||
''
|
||||
DUCKDNS_PROPAGATION_TIMEOUT=120
|
||||
@@ -71,17 +72,24 @@ in {
|
||||
routers = {
|
||||
# --- Router for the Traefik dashboard (optional) ---
|
||||
dashboard-router = {
|
||||
rule = "Host(`traefik.susano-test.duckdns.org`)"; # Example: A local-only subdomain
|
||||
rule = "Host(`traefik.${domain}`)"; # Example: A local-only subdomain
|
||||
entryPoints = [ "websecure" ];
|
||||
service = "api@internal"; # Special service for the dashboard
|
||||
tls.certResolver = "duckdns";
|
||||
};
|
||||
|
||||
immich-router = {
|
||||
rule = "Host(`immich.susano-test.duckdns.org`)"; # 1. The new domain
|
||||
entryPoints = [ "websecure" ]; # 2. Listen on HTTPS
|
||||
service = "immich-service"; # 3. Link to the new Immich service
|
||||
tls.certResolver = "duckdns"; # 4. Use the same SSL resolver
|
||||
rule = "Host(`immich.${domain}`)";
|
||||
entryPoints = [ "websecure" ];
|
||||
service = "immich-service";
|
||||
tls.certResolver = "duckdns";
|
||||
};
|
||||
|
||||
copyparty = mkIf config.dov.file-server.copyparty.enable {
|
||||
rule = "Host(`copyparty.${domain}`)";
|
||||
entryPoints = [ "websecure" ];
|
||||
service = "copyparty-service";
|
||||
tls.certResolver = "duckdns";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -92,6 +100,13 @@ in {
|
||||
{ url = "http://192.168.1.57:2283"; }
|
||||
];
|
||||
};
|
||||
|
||||
copyparty-service = mkIf config.dov.file-server.copyparty.enable {
|
||||
loadBalancer.servers = [
|
||||
# The backend URL for Immich
|
||||
{ url = "http://192.168.1.85:3923"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
middlewares = {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.dov.samba;
|
||||
ip = "192.168.1.88";
|
||||
in {
|
||||
options.dov.samba = {
|
||||
enable = mkEnableOption "samba share config";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
sops.secrets.smb-secrets = {
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs.cifs-utils ];
|
||||
|
||||
fileSystems."/MEDIA" = {
|
||||
device = "//${ip}/MEDIA";
|
||||
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=/run/secrets/smb-secrets"];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user