Skip to content

Commit 6e96944

Browse files
committed
chore: module for deployment in nixos
1 parent 1911e31 commit 6e96944

File tree

2 files changed

+197
-1
lines changed

2 files changed

+197
-1
lines changed

flake.nix

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,9 @@
3131

3232
packages.default = pkgs.callPackage ./default.nix {inherit pkgs;};
3333
}
34-
);
34+
)
35+
// {
36+
# Deployment module
37+
nixosModules.server = import ./module.nix self;
38+
};
3539
}

module.nix

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# Refer to this for more:
2+
# https://www.reddit.com/r/NixOS/comments/1fxf0am/setting_up_a_nextjs_project_as_a_systemd_service/
3+
flake: {
4+
config,
5+
lib,
6+
pkgs,
7+
...
8+
}: let
9+
# Shortcut config
10+
cfg = config.services.devops-journey;
11+
12+
# Packaged server
13+
server = flake.packages.${pkgs.stdenv.hostPlatform.system}.default;
14+
15+
# Caddy module lugin
16+
caddy = lib.mkIf (cfg.enable && cfg.proxy.enable && cfg.proxy.proxy == "caddy") {
17+
services.caddy.virtualHosts = lib.debug.traceIf (builtins.isNull cfg.proxy.domain) "proxy.domain can't be null, please specicy it properly!" {
18+
"${cfg.proxy.domain}" = {
19+
extraConfig = ''
20+
reverse_proxy 127.0.0.1:${toString cfg.port}
21+
'';
22+
};
23+
};
24+
};
25+
26+
# Nginx module plugin
27+
nginx = lib.mkIf (cfg.enable && cfg.proxy.enable && cfg.proxy.proxy == "nginx") {
28+
services.nginx.virtualHosts = lib.debug.traceIf (builtins.isNull cfg.proxy.domain) "proxy.domain can't be null, please specicy it properly!" {
29+
"${cfg.proxy.domain}" = {
30+
addSSL = true;
31+
enableACME = true;
32+
locations."/" = {
33+
proxyPass = "http://127.0.0.1:${toString cfg.port}";
34+
proxyWebsockets = true;
35+
};
36+
};
37+
};
38+
};
39+
40+
# The systemd service
41+
service = lib.mkIf cfg.enable {
42+
users.users.${cfg.user} = {
43+
description = "DevOps Journey Website user";
44+
isSystemUser = true;
45+
group = cfg.group;
46+
};
47+
48+
users.groups.${cfg.group} = {};
49+
50+
systemd.services.devops-journey = {
51+
description = "Official website of DevOps Journey";
52+
documentation = ["https://github.com/devops-journey"];
53+
54+
environment = {
55+
PORT = "${toString cfg.port}";
56+
HOSTNAME = cfg.host;
57+
NODE_ENV = "production";
58+
};
59+
60+
after = ["network-online.target"];
61+
wants = ["network-online.target"];
62+
wantedBy = ["multi-user.target"];
63+
64+
serviceConfig = {
65+
User = cfg.user;
66+
Group = cfg.group;
67+
Restart = "always";
68+
ExecStart = "${lib.getExe cfg.package}";
69+
StateDirectory = cfg.user;
70+
StateDirectoryMode = "0750";
71+
CapabilityBoundingSet = [
72+
"AF_NETLINK"
73+
"AF_INET"
74+
"AF_INET6"
75+
];
76+
DeviceAllow = ["/dev/stdin r"];
77+
DevicePolicy = "strict";
78+
IPAddressAllow = "localhost";
79+
LockPersonality = true;
80+
NoNewPrivileges = true;
81+
PrivateDevices = true;
82+
PrivateTmp = true;
83+
PrivateUsers = true;
84+
ProtectClock = true;
85+
ProtectControlGroups = true;
86+
ProtectHome = true;
87+
ProtectHostname = true;
88+
ProtectKernelLogs = true;
89+
ProtectKernelModules = true;
90+
ProtectKernelTunables = true;
91+
ProtectSystem = "strict";
92+
ReadOnlyPaths = ["/"];
93+
RemoveIPC = true;
94+
RestrictAddressFamilies = [
95+
"AF_NETLINK"
96+
"AF_INET"
97+
"AF_INET6"
98+
];
99+
RestrictNamespaces = true;
100+
RestrictRealtime = true;
101+
RestrictSUIDSGID = true;
102+
SystemCallArchitectures = "native";
103+
SystemCallFilter = [
104+
"@system-service"
105+
"~@privileged"
106+
"~@resources"
107+
"@pkey"
108+
];
109+
UMask = "0027";
110+
};
111+
};
112+
};
113+
114+
asserts = lib.mkIf cfg.enable {
115+
warnings = [
116+
(lib.mkIf (cfg.proxy.enable && cfg.proxy.domain == null) "services.devops-journey.proxy.domain must be set in order to properly generate certificate!")
117+
];
118+
};
119+
in {
120+
options = with lib; {
121+
services.devops-journey = {
122+
enable = mkEnableOption ''
123+
DevOps Journey website.
124+
'';
125+
126+
proxy = {
127+
enable = mkEnableOption ''
128+
Proxy reversed method of deployment
129+
'';
130+
131+
domain = mkOption {
132+
type = with types; nullOr str;
133+
default = null;
134+
example = "devops-journey.uz";
135+
description = "Domain to use while adding configurations to web proxy server";
136+
};
137+
138+
proxy = mkOption {
139+
type = with types;
140+
nullOr (enum [
141+
"nginx"
142+
"caddy"
143+
]);
144+
default = "caddy";
145+
description = "Proxy reverse software for hosting website";
146+
};
147+
};
148+
149+
host = mkOption {
150+
type = types.str;
151+
default = "127.0.0.1";
152+
description = "Hostname for nextjs server to bind";
153+
};
154+
155+
port = mkOption {
156+
type = types.int;
157+
default = 8455;
158+
description = "Port to use for passing over proxy";
159+
};
160+
161+
user = mkOption {
162+
type = types.str;
163+
default = "devops-journey";
164+
description = "User for running system + accessing keys";
165+
};
166+
167+
group = mkOption {
168+
type = types.str;
169+
default = "devops-journey";
170+
description = "Group for running system + accessing keys";
171+
};
172+
173+
dataDir = mkOption {
174+
type = types.str;
175+
default = "/var/lib/devops-journey/";
176+
description = lib.mdDoc ''
177+
The path where DevOps Journey Website server keeps data and possibly logs.
178+
'';
179+
};
180+
181+
package = mkOption {
182+
type = types.package;
183+
default = server;
184+
description = ''
185+
Packaged devops-journey.uz website contents for service.
186+
'';
187+
};
188+
};
189+
};
190+
191+
config = lib.mkMerge [asserts service caddy nginx];
192+
}

0 commit comments

Comments
 (0)