tangled
alpha
login
or
join now
wiro.world
/
dotfiles
2
fork
atom
yep, more dotfiles
2
fork
atom
overview
issues
1
pulls
1
pipelines
weird-row-server: cleanup config
wiro.world
1 month ago
15a6f760
dd5ef127
verified
This commit was signed with the committer's
known signature
.
wiro.world
SSH Key Fingerprint:
SHA256:SmMcWpNAnL+VAgItSawvXgdPVn7f1rsyAuB/5VNclKY=
+116
-106
9 changed files
expand all
collapse all
unified
split
globals.nix
hosts
weird-row-server
authelia.nix
caddy.nix
default.nix
grafana.nix
headscale.nix
secrets
default.nix
tailscale.nix
thelounge.nix
+1
-3
globals.nix
···
7
7
# wiro.world Public
8
8
authelia = "auth.${wiro-world}";
9
9
goatcounter = "stats.${wiro-world}";
10
10
-
grafana = "console.${wiro-world}";
11
10
headscale = "headscale.${wiro-world}";
12
11
matrix = "matrix.${wiro-world}";
13
12
miniflux = "news.${wiro-world}";
14
14
-
pages = "pages.${wiro-world}";
15
13
pds = "pds.${wiro-world}";
16
16
-
static = "static.${wiro-world}";
17
14
tangled-knot = "knot.${wiro-world}";
18
15
tangled-spindle = "spindle.${wiro-world}";
19
16
vaultwarden = "vault.${wiro-world}";
20
17
website = wiro-world;
21
18
22
19
# wiro.world private net
20
20
+
grafana = "console.${wiro-world-net}";
23
21
lldap = "ldap.${wiro-world-net}";
24
22
thelounge = "irc-lounge.${wiro-world-net}";
25
23
warrior = "warrior.${wiro-world-net}";
+7
hosts/weird-row-server/authelia.nix
···
174
174
175
175
systemd.services.authelia.after = [ "lldap.service" ];
176
176
177
177
+
services.prometheus.scrapeConfigs = [
178
178
+
{
179
179
+
job_name = "authelia";
180
180
+
static_configs = [ { targets = [ "localhost:${config.local.ports.authelia-metrics.string}" ]; } ];
181
181
+
}
182
182
+
];
183
183
+
177
184
services.caddy = {
178
185
virtualHosts.${globals.domains.authelia}.extraConfig = ''
179
186
reverse_proxy http://localhost:${config.local.ports.authelia.string}
+62
hosts/weird-row-server/caddy.nix
···
1
1
+
{
2
2
+
config,
3
3
+
pkgs,
4
4
+
globals,
5
5
+
...
6
6
+
}:
7
7
+
8
8
+
{
9
9
+
config = {
10
10
+
local.ports.caddy-http = {
11
11
+
number = 80;
12
12
+
public = true;
13
13
+
};
14
14
+
local.ports.caddy-https = {
15
15
+
number = 443;
16
16
+
public = true;
17
17
+
};
18
18
+
local.ports.caddy-metrics = 2019;
19
19
+
20
20
+
age.secrets.caddy-env.file = secrets/caddy-env.age;
21
21
+
22
22
+
# ensure caddy can access dns challenge wildcard certificates
23
23
+
users.users.caddy.extraGroups = [ "agnos" ];
24
24
+
25
25
+
services.caddy = {
26
26
+
enable = true;
27
27
+
package = pkgs.caddy.withPlugins {
28
28
+
plugins = [
29
29
+
"github.com/tailscale/caddy-tailscale@v0.0.0-20251016213337-01d084e119cb"
30
30
+
];
31
31
+
hash = "sha256-qqbU0PYWIMDYnJ3M+7RgQ+d9wfFUcNShOv7x50YIEj4=";
32
32
+
};
33
33
+
34
34
+
environmentFile = config.age.secrets.caddy-env.path;
35
35
+
36
36
+
globalConfig = ''
37
37
+
tailscale {
38
38
+
# this caddy instance already proxies headscale but needs to access headscale to start
39
39
+
# control_url https://headscale.wiro.world
40
40
+
control_url http://localhost:${config.local.ports.headscale.string}
41
41
+
42
42
+
ephemeral
43
43
+
}
44
44
+
'';
45
45
+
46
46
+
virtualHosts.${globals.domains.website}.extraConfig =
47
47
+
# TODO: host website on server with automatic deployment
48
48
+
''
49
49
+
reverse_proxy https://mrnossiom.github.io {
50
50
+
header_up Host {http.request.host}
51
51
+
}
52
52
+
'';
53
53
+
};
54
54
+
55
55
+
services.prometheus.scrapeConfigs = [
56
56
+
{
57
57
+
job_name = "caddy";
58
58
+
static_configs = [ { targets = [ "localhost:${config.local.ports.caddy-metrics.string}" ]; } ];
59
59
+
}
60
60
+
];
61
61
+
};
62
62
+
}
+5
-58
hosts/weird-row-server/default.nix
···
1
1
{
2
2
self,
3
3
-
config,
4
4
-
pkgs,
5
5
-
globals,
6
3
...
7
4
}:
8
5
···
25
22
26
23
./agnos.nix
27
24
./authelia.nix
28
28
-
# ./git-pages.nix
25
25
+
./caddy.nix
29
26
./goatcounter.nix
30
27
./grafana.nix
31
28
./headscale.nix
···
33
30
./lldap.nix
34
31
./miniflux.nix
35
32
./pds.nix
33
33
+
./tailscale.nix
36
34
./tangled.nix
37
35
./thelounge.nix
38
36
./tuwunel.nix
39
37
./vaultwarden.nix
40
38
./warrior.nix
41
39
./webfinger.nix
40
40
+
41
41
+
# doesn't support domain restrictions
42
42
+
# ./git-pages.nix
42
43
];
43
44
44
45
config = {
···
94
95
};
95
96
services.openssh.enable = true;
96
97
97
97
-
# age.secrets.tailscale-authkey.file = secrets/tailscale-authkey.age;
98
98
-
services.tailscale = {
99
99
-
enable = true;
100
100
-
extraSetFlags = [ "--advertise-exit-node" ];
101
101
-
# authKeyFile = config.age.secrets.tailscale-authkey.path;
102
102
-
authKeyParameters = {
103
103
-
baseURL = "https://${globals.domains.headscale}";
104
104
-
ephemeral = true;
105
105
-
preauthorized = true;
106
106
-
};
107
107
-
};
108
108
-
109
98
security.sudo.wheelNeedsPassword = false;
110
99
111
100
local.fragment.nix.enable = true;
···
127
116
};
128
117
129
118
jails = { };
130
130
-
};
131
131
-
132
132
-
local.ports.caddy-http = {
133
133
-
number = 80;
134
134
-
public = true;
135
135
-
};
136
136
-
local.ports.caddy-https = {
137
137
-
number = 443;
138
138
-
public = true;
139
139
-
};
140
140
-
141
141
-
age.secrets.caddy-env.file = secrets/caddy-env.age;
142
142
-
users.users.caddy.extraGroups = [ "agnos" ];
143
143
-
services.caddy = {
144
144
-
enable = true;
145
145
-
package = pkgs.caddy.withPlugins {
146
146
-
plugins = [
147
147
-
"github.com/caddy-dns/hetzner/v2@v2.0.0-preview-1"
148
148
-
"github.com/tailscale/caddy-tailscale@v0.0.0-20251016213337-01d084e119cb"
149
149
-
];
150
150
-
hash = "sha256-muKwDYs5Jp4ib/psZxpp1Kyfsqz6wPz/lpHFGtx67uY=";
151
151
-
};
152
152
-
153
153
-
environmentFile = config.age.secrets.caddy-env.path;
154
154
-
155
155
-
globalConfig = ''
156
156
-
tailscale {
157
157
-
# this caddy instance already proxies headscale but needs to access headscale to start
158
158
-
# control_url https://headscale.wiro.world
159
159
-
control_url http://localhost:${config.local.ports.headscale.string}
160
160
-
161
161
-
ephemeral
162
162
-
}
163
163
-
'';
164
164
-
165
165
-
virtualHosts.${globals.domains.website}.extraConfig =
166
166
-
# TODO: host website on server with automatic deployment
167
167
-
''
168
168
-
reverse_proxy https://mrnossiom.github.io {
169
169
-
header_up Host {http.request.host}
170
170
-
}
171
171
-
'';
172
119
};
173
120
174
121
# TODO: use bind to declare dns records declaratively
+10
-41
hosts/weird-row-server/grafana.nix
···
7
7
{
8
8
config = {
9
9
local.ports.grafana = 3002;
10
10
-
11
10
local.ports.prometheus = 9001;
12
11
local.ports.prometheus-node-exporter = 9002;
13
13
-
local.ports.tailscale-exporter = 9005;
14
14
-
local.ports.caddy-metrics = 2019;
15
15
-
local.ports.authelia-metrics = 9004;
16
16
-
local.ports.headscale-metrics = 9003;
17
12
18
13
age.secrets.grafana-oidc-secret = {
19
14
file = secrets/grafana-oidc-secret.age;
···
23
18
file = secrets/grafana-smtp-password.age;
24
19
owner = "grafana";
25
20
};
26
26
-
age.secrets.tailscale-exporter-env.file = secrets/tailscale-exporter-env.age;
21
21
+
27
22
services.grafana = {
28
23
enable = true;
29
24
···
88
83
enable = true;
89
84
port = config.local.ports.prometheus-node-exporter.number;
90
85
};
91
91
-
exporters.tailscale = {
92
92
-
enable = true;
93
93
-
port = config.local.ports.tailscale-exporter.number;
94
94
-
environmentFile = config.age.secrets.tailscale-exporter-env.path;
95
95
-
};
96
86
97
97
-
# TODO: move them to their respective modules
98
87
scrapeConfigs = [
99
88
{
100
100
-
job_name = "caddy";
101
101
-
static_configs = [ { targets = [ "localhost:${config.local.ports.caddy-metrics.string}" ]; } ];
102
102
-
}
103
103
-
{
104
89
job_name = "node-exporter";
105
90
static_configs = [
106
91
{ targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; }
107
107
-
108
108
-
];
109
109
-
}
110
110
-
{
111
111
-
job_name = "headscale";
112
112
-
static_configs = [ { targets = [ "localhost:${config.local.ports.headscale-metrics.string}" ]; } ];
113
113
-
}
114
114
-
{
115
115
-
job_name = "authelia";
116
116
-
static_configs = [ { targets = [ "localhost:${config.local.ports.authelia-metrics.string}" ]; } ];
117
117
-
}
118
118
-
{
119
119
-
job_name = "tailscale";
120
120
-
static_configs = [
121
121
-
{ targets = [ "localhost:${toString config.services.prometheus.exporters.tailscale.port}" ]; }
122
92
];
123
93
}
124
94
];
125
95
};
126
96
127
127
-
services.caddy = {
128
128
-
globalConfig = ''
129
129
-
metrics { per_host }
130
130
-
'';
131
131
-
# virtualHosts."http://${globals.domains.grafana}".extraConfig = ''
132
132
-
# bind tailscale/console
133
133
-
virtualHosts.${globals.domains.grafana}.extraConfig = ''
134
134
-
reverse_proxy http://localhost:${config.local.ports.grafana.string}
135
135
-
'';
136
136
-
};
97
97
+
services.caddy.globalConfig = ''
98
98
+
metrics { per_host }
99
99
+
'';
100
100
+
101
101
+
services.caddy.virtualHosts.${globals.domains.grafana}.extraConfig = ''
102
102
+
bind tailscale/console
103
103
+
tls /var/lib/agnos/net.wiro.world_fullchain.pem /var/lib/agnos/net.wiro.world_privkey.pem
104
104
+
reverse_proxy http://localhost:${config.local.ports.grafana.string}
105
105
+
'';
137
106
};
138
107
}
+8
-1
hosts/weird-row-server/headscale.nix
···
11
11
{
12
12
config = {
13
13
local.ports.headscale = 3006;
14
14
-
14
14
+
local.ports.headscale-metrics = 9003;
15
15
local.ports.headscale-derp = {
16
16
number = 3478;
17
17
public = true;
···
91
91
92
92
# headscale only starts if oidc is available
93
93
systemd.services.headscale.after = [ "authelia-main.service" ];
94
94
+
95
95
+
services.prometheus.scrapeConfigs = [
96
96
+
{
97
97
+
job_name = "headscale";
98
98
+
static_configs = [ { targets = [ "localhost:${config.local.ports.headscale-metrics.string}" ]; } ];
99
99
+
}
100
100
+
];
94
101
95
102
services.caddy = {
96
103
virtualHosts.${globals.domains.headscale}.extraConfig = ''
-2
hosts/weird-row-server/secrets/default.nix
···
24
24
"miniflux-oidc-secret.age".publicKeys = deploy;
25
25
# Defines `PDS_JWT_SECRET`, `PDS_ADMIN_PASSWORD`, `PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX`, `PDS_EMAIL_SMTP_URL`, `PDS_EMAIL_FROM_ADDRESS`.
26
26
"pds-env.age".publicKeys = deploy;
27
27
-
# Defines `TAILSCALE_TAILNET`, `TAILSCALE_OAUTH_CLIENT_ID`, `TAILSCALE_OAUTH_CLIENT_SECRET`.
28
28
-
"tailscale-exporter-env.age".publicKeys = deploy;
29
27
"tuwunel-registration-tokens.age".publicKeys = deploy;
30
28
# Defines `SMTP_PASSWORD`
31
29
"vaultwarden-env.age".publicKeys = deploy;
+22
hosts/weird-row-server/tailscale.nix
···
1
1
+
{
2
2
+
globals,
3
3
+
...
4
4
+
}:
5
5
+
6
6
+
{
7
7
+
config = {
8
8
+
local.ports.tailscale-exporter = 9005;
9
9
+
10
10
+
# age.secrets.tailscale-authkey.file = secrets/tailscale-authkey.age;
11
11
+
services.tailscale = {
12
12
+
enable = true;
13
13
+
extraSetFlags = [ "--advertise-exit-node" ];
14
14
+
# authKeyFile = config.age.secrets.tailscale-authkey.path;
15
15
+
authKeyParameters = {
16
16
+
baseURL = "https://${globals.domains.headscale}";
17
17
+
ephemeral = true;
18
18
+
preauthorized = true;
19
19
+
};
20
20
+
};
21
21
+
};
22
22
+
}
+1
-1
hosts/weird-row-server/thelounge.nix
···
23
23
24
24
services.caddy = {
25
25
virtualHosts.${globals.domains.thelounge}.extraConfig = ''
26
26
-
bind tailscale/irc-lounge
26
26
+
bind tailscale/irc
27
27
tls /var/lib/agnos/net.wiro.world_fullchain.pem /var/lib/agnos/net.wiro.world_privkey.pem
28
28
reverse_proxy http://localhost:${toString config.services.thelounge.port}
29
29
'';