I want a private file host for things I can't put on our main copyparty instance. I'll host that on umber
+138
packetmix/systems/umber/copyparty.nix
+138
packetmix/systems/umber/copyparty.nix
···
1
+
# SPDX-FileCopyrightText: 2025 FreshlyBakedCake
2
+
#
3
+
# SPDX-License-Identifier: MIT
4
+
5
+
{
6
+
project,
7
+
pkgs,
8
+
config,
9
+
lib,
10
+
...
11
+
}:
12
+
{
13
+
imports = [
14
+
project.inputs.copyparty.result.nixosModules.default
15
+
];
16
+
17
+
config = {
18
+
nixpkgs.overlays = [ project.inputs.copyparty.result.overlays.default ];
19
+
20
+
services.copyparty =
21
+
let
22
+
admins = [
23
+
"minion"
24
+
];
25
+
in
26
+
{
27
+
enable = true;
28
+
29
+
settings = {
30
+
i = "127.0.0.1"; # ip
31
+
p = 1030; # port
32
+
33
+
# we'll be using nginx for this...
34
+
http-only = true;
35
+
no-crt = true;
36
+
37
+
idp-store = 3;
38
+
idp-h-usr = "X-Webauth-Login";
39
+
idp-adm = admins;
40
+
have-idp-hdrs = 1; # https://github.com/9001/copyparty/issues/849
41
+
42
+
shr = "/share";
43
+
shr-db = "/var/lib/copyparty/shares.db";
44
+
shr-adm = admins;
45
+
46
+
# as we might have private directories, better to be a bit conservative about permissions...
47
+
chmod-f = 700;
48
+
chmod-d = 700;
49
+
50
+
magic = true; # "enable filetype detection on nameless uploads"
51
+
52
+
e2dsa = true; # index files to allow searching, upload undo, etc.
53
+
e2ts = true; # and scan metadata...
54
+
55
+
rss = true; # allow (experimental) rss support -> useful for antennapod/miniflux/co.
56
+
dav-auth = true; # "force auth for all folders" notably "(required by davfs2 when only some folders are world-readable)"
57
+
58
+
xvol = true; # don't allow symlinks to break out of confinement...
59
+
no-robots = true; # not really meant to be indexed. Maybe we want to add anubis at some point too...
60
+
61
+
ah-alg = "argon2";
62
+
63
+
spinner = "⭐"; # [hopefully this isn't too boring for you, tripflag](https://github.com/9001/copyparty/tree/hovudstraum/docs/rice#boring-loader-spinner)
64
+
65
+
xm = "aw,f,j,t3600,${project.inputs.copyparty.src}/bin/hooks/wget.py"; # download URLs that are pasted into the message box
66
+
67
+
xff-src = "127.0.0.1";
68
+
rproxy = 1;
69
+
70
+
exp = true;
71
+
};
72
+
73
+
volumes = {
74
+
"/" = {
75
+
path = "/var/lib/copyparty/data";
76
+
77
+
access = {
78
+
r = "*";
79
+
A = admins;
80
+
};
81
+
};
82
+
"/private" = {
83
+
path = "/var/lib/copyparty/private";
84
+
85
+
access = {
86
+
A = [
87
+
"minion"
88
+
];
89
+
};
90
+
};
91
+
};
92
+
};
93
+
94
+
systemd.services.copyparty = {
95
+
path = [ pkgs.wget ]; # Needed for downloading files by URL
96
+
serviceConfig = {
97
+
BindReadOnlyPaths = [
98
+
"/etc/ssl"
99
+
"/etc/static/ssl"
100
+
]; # Required for wget to validate SSL for downloads
101
+
StateDirectory =
102
+
"copyparty "
103
+
+ (lib.pipe config.services.copyparty.volumes [
104
+
builtins.attrValues
105
+
(map (mount: mount.path))
106
+
(map (lib.removePrefix "/var/lib/"))
107
+
(lib.concatStringsSep " ")
108
+
]);
109
+
};
110
+
};
111
+
112
+
services.nginx.enable = true;
113
+
114
+
services.nginx.virtualHosts."copyparty.starrysky.fyi" = {
115
+
serverName = "copyparty.starrysky.fyi";
116
+
117
+
addSSL = true;
118
+
enableACME = true;
119
+
acmeRoot = null;
120
+
121
+
locations."/" = {
122
+
proxyPass = "http://127.0.0.1:1030";
123
+
recommendedProxySettings = true;
124
+
proxyWebsockets = true;
125
+
};
126
+
127
+
extraConfig = ''
128
+
client_max_body_size 1024M;
129
+
'';
130
+
};
131
+
services.nginx.tailscaleAuth = {
132
+
enable = true;
133
+
virtualHosts = [ "copyparty.starrysky.fyi" ];
134
+
};
135
+
136
+
clicks.storage.impermanence.persist.directories = [ "/var/lib/copyparty" ];
137
+
};
138
+
}