Compare commits

..

2 commits

Author SHA1 Message Date
Rustam Efimov
793eeb3161
feat(users/rus07tam): enable openclaw gateway via systemd
Some checks failed
Nix CI / build (push) Failing after 3m36s
2026-04-01 09:56:24 +03:00
Rustam Efimov
e2bd4444d2
chore: apply nix fmt 2026-04-01 09:54:15 +03:00
48 changed files with 275 additions and 187 deletions

View file

@ -1,11 +1,13 @@
{dns, ...}: let
{ dns, ... }:
let
domain = "ruject.fun";
database = {
host = "127.0.0.1";
port = 5432;
};
ipv4 = "94.156.112.0";
in {
in
{
services.nginx.enable = true;
machine = {
gateway = "10.0.0.1";
@ -29,7 +31,7 @@ in {
"ns2"
];
A = [ipv4];
A = [ ipv4 ];
subdomains = rec {
ns1 = host ipv4 null;
@ -52,10 +54,10 @@ in {
};
TXT = [
(with spf; strict ["a:mail.ruject.fun"])
(with spf; strict [ "a:mail.ruject.fun" ])
];
MX = with mx; [(mx 10 "mail.ruject.fun.")];
MX = with mx; [ (mx 10 "mail.ruject.fun.") ];
DMARC = [
{

View file

@ -6,7 +6,8 @@
let
cfg = config.machine.bind;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
networking.firewall = {
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];

View file

@ -7,7 +7,8 @@
let
cfg = config.machine.bind;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
services.bind = {
enable = cfg.enable;
listenOnPort = cfg.port;

View file

@ -6,7 +6,8 @@
let
cfg = config.machine.code-server;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
services.nginx.virtualHosts = mkIf (cfg.domain != null) {
${cfg.domain} = {
enableACME = true;

View file

@ -6,7 +6,8 @@
let
cfg = config.machine.code-server;
in
with lib; {
with lib;
{
options.machine.code-server = {
enable = mkEnableOption "code-server";
port = mkOption {

View file

@ -7,7 +7,8 @@
let
cfg = config.machine.code-server;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
services.code-server = {
enable = cfg.enable;
port = cfg.port;

View file

@ -6,7 +6,8 @@
let
cfg = config.machine.coturn;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
networking.firewall = {
interfaces.enp2s0 =
let

View file

@ -12,7 +12,8 @@ let
realm
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.coturn = rec {
inherit realm enable;
no-cli = true;

View file

@ -9,7 +9,8 @@ let
inherit (config.machine.forgejo) domain;
address = "noreply@${domain}";
in
with lib; mkIf config.machine.mail.enable {
with lib;
mkIf config.machine.mail.enable {
services.forgejo = {
secrets = {
mailer.PASSWD = sec."mail/servicePassword".path;

View file

@ -10,19 +10,22 @@ let
port
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
networking.firewall = {
allowedTCPPorts = [ port ];
};
services.nginx.virtualHosts = with lib; mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://[::1]:${toString port}";
proxyWebsockets = true;
services.nginx.virtualHosts =
with lib;
mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://[::1]:${toString port}";
proxyWebsockets = true;
};
};
};
};
}

View file

@ -9,7 +9,8 @@ let
url = config.services.forgejo.settings.server.ROOT_URL;
cfg = config.machine.forgejo;
in
with lib; mkIf cfg.enableRunner {
with lib;
mkIf cfg.enableRunner {
sops.secrets = {
"forgejo/runnerToken" = {
sopsFile = ./../../secrets/common.yaml;

View file

@ -7,7 +7,8 @@ let
cfg = config.machine.forgejo;
customDir = config.services.forgejo.customDir;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
systemd.tmpfiles.rules = [
"d '${customDir}/templates' - forgejo forgejo - -"
"d '${customDir}/public' - forgejo forgejo - -"

View file

@ -6,7 +6,8 @@
let
inherit (config.machine.mail) enable;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.rspamd = {
enable = true;
overrides = {

View file

@ -7,7 +7,8 @@
let
inherit (config.machine.mail) enable;
in
with lib; mkIf enable {
with lib;
mkIf enable {
systemd.tmpfiles.rules = [
"C /var/dkim/default.private 0600 root root - - ${sec.dkim_default_private.path}"
];

View file

@ -9,7 +9,8 @@ let
port
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
networking.firewall.allowedTCPPorts = [
port
];

View file

@ -10,7 +10,8 @@ let
port
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.minecraft-server = {
inherit enable;
dataDir = "/var/lib/minecraft";

View file

@ -6,7 +6,8 @@
let
cfg = config.machine.mysql;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
networking.firewall = {
allowedTCPPorts = [ cfg.port ];
};

View file

@ -10,7 +10,8 @@ let
enable
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.mysql = {
inherit enable;
package = pkgs.mysql84;

View file

@ -11,17 +11,20 @@ let
folder
;
in
with lib; mkIf enable {
services.nginx.virtualHosts = with lib; mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://[::1]:${toString port}";
proxyWebsockets = true;
with lib;
mkIf enable {
services.nginx.virtualHosts =
with lib;
mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://[::1]:${toString port}";
proxyWebsockets = true;
};
};
};
};
services.navidrome = {
inherit enable;

View file

@ -1,8 +1,14 @@
{ config, lib, hostname, ... }:
{
config,
lib,
hostname,
...
}:
let
inherit (config.machine) ipv4 gateway;
in
with lib; {
with lib;
{
networking = {
hostName = hostname;
networkmanager.enable = mkDefault true;

View file

@ -7,7 +7,8 @@ let
pgsqlEnable = config.machine.postgresql.enable;
cfg = config.machine.nextcloud;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
services.nextcloud.config =
if pgsqlEnable then
{
@ -20,13 +21,15 @@ with lib; mkIf cfg.enable {
dbhost = "localhost";
};
services.postgresql = with lib; mkIf pgsqlEnable {
ensureDatabases = [ "nextcloud" ];
ensureUsers = [
{
name = "nextcloud";
ensureDBOwnership = true;
}
];
};
services.postgresql =
with lib;
mkIf pgsqlEnable {
ensureDatabases = [ "nextcloud" ];
ensureUsers = [
{
name = "nextcloud";
ensureDBOwnership = true;
}
];
};
}

View file

@ -11,7 +11,8 @@ let
;
address = "noreply@${host}";
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.nextcloud = {
settings = {
mail_smtpmode = "smtp";

View file

@ -8,7 +8,8 @@
let
cfg = config.machine.nextcloud;
in
with lib; mkIf cfg.enable {
with lib;
mkIf cfg.enable {
services.nextcloud = {
enable = cfg.enable;
appstoreEnable = false;

View file

@ -1,5 +1,6 @@
{ lib, config, ... }:
with lib; mkIf (config.services.nginx.enable) {
with lib;
mkIf (config.services.nginx.enable) {
security.acme = {
acceptTerms = true;
defaults = {

View file

@ -6,7 +6,8 @@
let
inherit (config.services.nginx) enable;
in
with lib; mkIf enable {
with lib;
mkIf enable {
networking.firewall.allowedTCPPorts = [
80
443

View file

@ -10,7 +10,8 @@ let
enable
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.postgresql = {
inherit enable;
settings = {

View file

@ -9,7 +9,8 @@ let
port
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.prometheus = {
inherit enable port;
};

View file

@ -8,7 +8,8 @@ let
enable
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
networking.firewall = {
allowedTCPPorts = [
# HTTP filer

View file

@ -11,7 +11,8 @@ let
localhost = "http://localhost:5280";
in
with lib; mkIf enable {
with lib;
mkIf enable {
security.acme.certs."${domain}".extraDomainNames = [
"conference.${domain}"
"upload.${domain}"
@ -19,36 +20,38 @@ with lib; mkIf enable {
users.groups.acme.members = [
"prosody"
];
services.nginx.virtualHosts = with lib; mkIf (domain != null) {
"${domain}".locations = {
"= /xmpp-websocket" = {
proxyPass = localhost;
proxyWebsockets = true;
services.nginx.virtualHosts =
with lib;
mkIf (domain != null) {
"${domain}".locations = {
"= /xmpp-websocket" = {
proxyPass = localhost;
proxyWebsockets = true;
};
"= /http-bind".proxyPass = localhost;
"/push".proxyPass = localhost;
"= /.well-known/host-meta".proxyPass = localhost;
"= /.well-known/host-meta.json".proxyPass = localhost;
};
"conference.${domain}" = {
http3 = true;
quic = true;
forceSSL = true;
kTLS = true;
useACMEHost = domain;
sslCertificate = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
sslCertificateKey = "${config.security.acme.certs.${domain}.directory}/key.pem";
locations."/".proxyPass = localhost;
};
"upload.${domain}" = {
http3 = true;
quic = true;
forceSSL = true;
kTLS = true;
useACMEHost = domain;
sslCertificate = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
sslCertificateKey = "${config.security.acme.certs.${domain}.directory}/key.pem";
locations."/".proxyPass = localhost;
};
"= /http-bind".proxyPass = localhost;
"/push".proxyPass = localhost;
"= /.well-known/host-meta".proxyPass = localhost;
"= /.well-known/host-meta.json".proxyPass = localhost;
};
"conference.${domain}" = {
http3 = true;
quic = true;
forceSSL = true;
kTLS = true;
useACMEHost = domain;
sslCertificate = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
sslCertificateKey = "${config.security.acme.certs.${domain}.directory}/key.pem";
locations."/".proxyPass = localhost;
};
"upload.${domain}" = {
http3 = true;
quic = true;
forceSSL = true;
kTLS = true;
useACMEHost = domain;
sslCertificate = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
sslCertificateKey = "${config.security.acme.certs.${domain}.directory}/key.pem";
locations."/".proxyPass = localhost;
};
};
}

View file

@ -12,7 +12,8 @@ let
sslCertDir = config.security.acme.certs."${domain}".directory;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.prosody = {
inherit enable;

View file

@ -10,7 +10,8 @@ let
enable
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
sops.secrets = {
"redis/password" = { };
};

View file

@ -10,7 +10,8 @@ let
domain
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.roundcube = {
inherit enable;
dicts = with pkgs.aspellDicts; [

View file

@ -7,20 +7,25 @@ let
pgsqlEnable = config.machine.postgresql.enable;
inherit (config.machine.synapse) enable;
in
with lib; mkIf enable {
services.postgresql = with lib; mkIf pgsqlEnable {
ensureUsers = [
{
name = "matrix-synapse";
ensureDBOwnership = true;
}
];
ensureDatabases = [ "matrix-synapse" ];
};
with lib;
mkIf enable {
services.postgresql =
with lib;
mkIf pgsqlEnable {
ensureUsers = [
{
name = "matrix-synapse";
ensureDBOwnership = true;
}
];
ensureDatabases = [ "matrix-synapse" ];
};
services.matrix-synapse.settings.database = {
name = if pgsqlEnable then "psycopg2" else "sqlite3";
args = with lib; mkIf pgsqlEnable {
host = "/run/postgresql";
};
args =
with lib;
mkIf pgsqlEnable {
host = "/run/postgresql";
};
};
}

View file

@ -52,7 +52,8 @@ let
};
};
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.nginx.virtualHosts.${domain} = {
enableACME = true;
forceSSL = true;

View file

@ -11,7 +11,8 @@ let
;
address = "noreply@${domain}";
in
with lib; mkIf (enable && config.machine.mail.enable) {
with lib;
mkIf (enable && config.machine.mail.enable) {
services.matrix-synapse = {
settings = {
admin_contact = address;

View file

@ -7,7 +7,8 @@ let
redisEnable = config.machine.redis.enable;
inherit (config.machine.synapse) enable;
in
with lib; mkIf (redisEnable && enable) {
with lib;
mkIf (redisEnable && enable) {
services.redis.servers.matrix-synapse = {
enable = true;
};

View file

@ -8,7 +8,8 @@ let
enable
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
sops.secrets = {
"matrix/registrationSharedSecret" = {
sopsFile = ./../../secrets/common.yaml;
@ -40,7 +41,9 @@ with lib; mkIf enable {
smtp_pass: ${config.sops.placeholder."mail/servicePassword"}
'';
};
services.matrix-synapse.extraConfigFiles = with lib; mkIf config.machine.synapse.enable [
config.sops.templates.matrix-synapse-config.path
];
services.matrix-synapse.extraConfigFiles =
with lib;
mkIf config.machine.synapse.enable [
config.sops.templates.matrix-synapse-config.path
];
}

View file

@ -12,7 +12,8 @@ let
metrics
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.matrix-synapse = {
inherit enable;
enableRegistrationScript = true;

View file

@ -6,7 +6,8 @@
let
inherit (config.machine.coturn) enable;
in
with lib; mkIf (enable && config.machine.coturn.enable) {
with lib;
mkIf (enable && config.machine.coturn.enable) {
services.matrix-synapse.settings = with config.services.coturn; {
turn_uris = [
"turn:${realm}:3478?transport=udp"

View file

@ -10,7 +10,8 @@ let
port
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
services.uptime-kuma = {
inherit enable;
settings = {
@ -18,16 +19,18 @@ with lib; mkIf enable {
};
};
services.nginx.virtualHosts = with lib; mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
services.nginx.virtualHosts =
with lib;
mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
};
};
};
};
networking.firewall = {
allowedTCPPorts = [ port ];

View file

@ -10,34 +10,37 @@ let
port
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
networking.firewall = {
allowedTCPPorts = [ port ];
};
services.nginx.virtualHosts = with lib; mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
services.nginx.virtualHosts =
with lib;
mkIf (domain != null) {
"${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
extraConfig = ''
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
'';
};
extraConfig = ''
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy same-origin;
add_header X-XSS-Protection "1; mode=block";
'';
};
extraConfig = ''
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy same-origin;
add_header X-XSS-Protection "1; mode=block";
'';
};
};
services.vaultwarden = {
inherit enable;

View file

@ -9,7 +9,8 @@ let
port
;
in
with lib; mkIf enable {
with lib;
mkIf enable {
networking.firewall.allowedTCPPorts = [
# Web panel
port

View file

@ -2,43 +2,50 @@
lib,
config,
...
}: let
inherit
(config.machine.xray-3x-ui)
}:
let
inherit (config.machine.xray-3x-ui)
enable
port
domain
subscriptions
;
in {
services.nginx.virtualHosts = with lib; mkIf enable {
${domain} = with lib; mkIf (domain != null) {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
extraConfig = ''
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
'';
};
in
{
services.nginx.virtualHosts =
with lib;
mkIf enable {
${domain} =
with lib;
mkIf (domain != null) {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
extraConfig = ''
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
'';
};
};
${subscriptions.domain} =
with lib;
mkIf (subscriptions.domain != null) {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:2096";
proxyWebsockets = true;
extraConfig = ''
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
'';
};
};
};
${subscriptions.domain} = with lib; mkIf (subscriptions.domain != null) {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:2096";
proxyWebsockets = true;
extraConfig = ''
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
'';
};
};
};
}

View file

@ -1,6 +1,11 @@
# See https://github.com/sunmeplz/xray-3x-ui
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
@ -11,8 +16,7 @@ let
minGoVersion = "1.26.0";
xray-3x-ui =
assert assertMsg
(versionAtLeast pkgs.go.version minGoVersion)
assert assertMsg (versionAtLeast pkgs.go.version minGoVersion)
"3x-ui requires Go >= ${minGoVersion}, but ${pkgs.go.version} is available";
pkgs.buildGoModule rec {
@ -28,7 +32,10 @@ let
vendorHash = "sha256-M8YQTMfF/xZut4hxUcAfF2xGK625vwJNp4JS/zoXUCQ=";
ldflags = [ "-s" "-w" ];
ldflags = [
"-s"
"-w"
];
meta = with lib; {
description = "Xray panel supporting multi-protocol multi-user";
@ -39,7 +46,8 @@ let
};
};
in {
in
{
# Service implementation
config = mkIf cfg.enable {
# User and group configuration
@ -85,8 +93,14 @@ in {
Group = "xray-3x-ui";
StateDirectory = "3x-ui 3x-ui/bin 3x-ui/logs";
StateDirectoryMode = "0755";
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" "CAP_NET_ADMIN" ];
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_NET_ADMIN" ];
AmbientCapabilities = [
"CAP_NET_BIND_SERVICE"
"CAP_NET_ADMIN"
];
CapabilityBoundingSet = [
"CAP_NET_BIND_SERVICE"
"CAP_NET_ADMIN"
];
};
};

View file

@ -7,6 +7,7 @@
programs.openclaw = {
enable = true;
installApp = false;
systemd.enable = true;
bundledPlugins = {
summarize.enable = true;