Skip to content

Commit 95cb749

Browse files
committed
feat: nix module for easy deployment
1 parent 51a773c commit 95cb749

File tree

3 files changed

+213
-2
lines changed

3 files changed

+213
-2
lines changed

flake.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@
3535
)
3636
// {
3737
# Overlay module
38-
# nixosModules.rustina.bot = import ./module.nix self;
38+
nixosModules.rustina.bot = import ./module.nix self;
3939
};
4040
}

module.nix

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# Template & Guide from
2+
# https://github.com/reckenrode/nix-foundryvtt/blob/main/modules/foundryvtt/default.nix
3+
flake: {
4+
config,
5+
lib,
6+
pkgs,
7+
...
8+
}: let
9+
cfg = config.services.rustina.bot;
10+
bot = flake.packages.${pkgs.stdenv.hostPlatform.system}.default;
11+
12+
genArgs = {cfg}: let
13+
token = cfg.token;
14+
domain = cfg.webhook.domain or "";
15+
mode =
16+
if cfg.webhook.enable
17+
then "webhook"
18+
else "polling";
19+
port =
20+
if cfg.webhook.enable
21+
then "--port ${toString cfg.webhook.port}"
22+
else "";
23+
in
24+
lib.strings.concatStringsSep " " [mode token domain port];
25+
26+
caddy = lib.mkIf (cfg.enable && cfg.webhook.enable && cfg.webhook.proxy == "caddy") {
27+
services.caddy.virtualHosts = lib.debug.traceIf (builtins.isNull cfg.webhook.domain) "webhook.domain can't be null, please specicy it properly!" {
28+
"${cfg.webhook.domain}" = {
29+
extraConfig = ''
30+
reverse_proxy 127.0.0.1:${toString cfg.webhook.port}
31+
'';
32+
};
33+
};
34+
};
35+
36+
nginx = lib.mkIf (cfg.enable && cfg.webhook.enable && cfg.webhook.proxy == "nginx") {
37+
services.nginx.virtualHosts = lib.debug.traceIf (builtins.isNull cfg.webhook.domain) "webhook.domain can't be null, please specicy it properly!" {
38+
"${cfg.webhook.domain}" = {
39+
addSSL = true;
40+
enableACME = true;
41+
locations."/" = {
42+
proxyPass = "http://127.0.0.1:${toString cfg.webhook.port}";
43+
proxyWebsockets = true;
44+
};
45+
};
46+
};
47+
};
48+
49+
service = lib.mkIf cfg.enable {
50+
users.users.${cfg.user} = {
51+
description = "Rustina Bot management user";
52+
isSystemUser = true;
53+
group = cfg.group;
54+
};
55+
56+
users.groups.${cfg.group} = {};
57+
58+
systemd.services.rustina-bot = {
59+
description = "Rustina Bot for managing telegram community";
60+
documentation = ["https://rust-lang.uz/"];
61+
62+
after = ["network-online.target"];
63+
wants = ["network-online.target"];
64+
wantedBy = ["multi-user.target"];
65+
66+
serviceConfig = {
67+
User = cfg.user;
68+
Group = cfg.group;
69+
Restart = "always";
70+
ExecStart = "${lib.getBin cfg.package}/bin/bot ${genArgs {cfg = cfg;}}";
71+
StateDirectory = cfg.user;
72+
StateDirectoryMode = "0750";
73+
# EnvironmentFile = cfg.secret;
74+
CapabilityBoundingSet = [
75+
"AF_NETLINK"
76+
"AF_INET"
77+
"AF_INET6"
78+
];
79+
DeviceAllow = ["/dev/stdin r"];
80+
DevicePolicy = "strict";
81+
IPAddressAllow = "localhost";
82+
LockPersonality = true;
83+
# MemoryDenyWriteExecute = true;
84+
NoNewPrivileges = true;
85+
PrivateDevices = true;
86+
PrivateTmp = true;
87+
PrivateUsers = true;
88+
ProtectClock = true;
89+
ProtectControlGroups = true;
90+
ProtectHome = true;
91+
ProtectHostname = true;
92+
ProtectKernelLogs = true;
93+
ProtectKernelModules = true;
94+
ProtectKernelTunables = true;
95+
ProtectSystem = "strict";
96+
ReadOnlyPaths = ["/"];
97+
RemoveIPC = true;
98+
RestrictAddressFamilies = [
99+
"AF_NETLINK"
100+
"AF_INET"
101+
"AF_INET6"
102+
];
103+
RestrictNamespaces = true;
104+
RestrictRealtime = true;
105+
RestrictSUIDSGID = true;
106+
SystemCallArchitectures = "native";
107+
SystemCallFilter = [
108+
"@system-service"
109+
"~@privileged"
110+
"~@resources"
111+
"@pkey"
112+
];
113+
UMask = "0027";
114+
};
115+
116+
# preStart = ''
117+
# installedConfigFile="${config.services.rustina.bot.dataDir}/Config/options.json"
118+
# install -d -m750 ${config.services.rustina.bot.dataDir}/Config
119+
# rm -f "$installedConfigFile" && install -m640 ${configFile} "$installedConfigFile"
120+
# '';
121+
};
122+
};
123+
124+
asserts = lib.mkIf cfg.enable {
125+
warnings = [
126+
(lib.mkIf (cfg.webhook.enable && cfg.webhook.domain == null) "services.rustina.bot.webhook.domain must be set in order to properly generate certificate!")
127+
];
128+
129+
assertions = [
130+
{
131+
assertion = cfg.token != null;
132+
message = "services.rustina.bot.token must be set!";
133+
}
134+
];
135+
};
136+
in {
137+
options = with lib; {
138+
services.rustina.bot = {
139+
enable = mkEnableOption ''
140+
Rustina Bot: Telegram bot made by Uzbek Rust team for Rust Uzbekistan community.
141+
'';
142+
143+
webhook = {
144+
enable = mkEnableOption ''
145+
Webhook method of deployment
146+
'';
147+
148+
domain = mkOption {
149+
type = with types; nullOr str;
150+
default = null;
151+
example = "rust-lang.uz";
152+
description = "Domain to use while adding configurations to web proxy server";
153+
};
154+
155+
proxy = mkOption {
156+
type = with types;
157+
nullOr (enum [
158+
"nginx"
159+
"caddy"
160+
]);
161+
default = "caddy";
162+
description = "Proxy reverse software for hosting webhook";
163+
};
164+
165+
port = mkOption {
166+
type = types.int;
167+
default = 8451;
168+
description = "Port to use for passing over proxy";
169+
};
170+
};
171+
172+
token = mkOption {
173+
type = with types; nullOr path;
174+
default = null;
175+
description = lib.mdDoc ''
176+
Path to telegram bot token of Rustina manager.
177+
'';
178+
};
179+
180+
user = mkOption {
181+
type = types.str;
182+
default = "rustina-bot";
183+
description = "User for running system + accessing keys";
184+
};
185+
186+
group = mkOption {
187+
type = types.str;
188+
default = "rustina-bot";
189+
description = "Group for running system + accessing keys";
190+
};
191+
192+
dataDir = mkOption {
193+
type = types.str;
194+
default = "/var/lib/rustina/bot";
195+
description = lib.mdDoc ''
196+
The path where Rustina Bot keeps its config, data, and logs.
197+
'';
198+
};
199+
200+
package = mkOption {
201+
type = types.package;
202+
default = bot;
203+
description = ''
204+
The Rustian Bot package to use with the service.
205+
'';
206+
};
207+
};
208+
};
209+
210+
config = lib.mkMerge [asserts service caddy nginx];
211+
}

shell.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ in
5858
5959
# Start watching for changes
6060
# Start watching for changes in the background
61-
# cargo watch -x "run --bin xinuxmgr" &
61+
# cargo watch -x "run --bin bot" &
6262
6363
# Store the PID of the background process
6464
# CARGO_WATCH_PID=$!

0 commit comments

Comments
 (0)