biotite: move services to new machines and new domain
- related services: forgejo, miniflux, vaultwarden - moved from xinyang.life to xiny.li - clean up modules
This commit is contained in:
parent
947e97ce4e
commit
ad9c205fc5
18 changed files with 263 additions and 670 deletions
|
@ -10,6 +10,10 @@
|
||||||
./services/gotosocial.nix
|
./services/gotosocial.nix
|
||||||
./services/synapse.nix
|
./services/synapse.nix
|
||||||
./services/restic.nix
|
./services/restic.nix
|
||||||
|
./services/miniflux.nix
|
||||||
|
./services/hedgedoc.nix
|
||||||
|
./services/forgejo.nix
|
||||||
|
./services/vaultwarden.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = "biotite";
|
networking.hostName = "biotite";
|
||||||
|
|
|
@ -5,6 +5,12 @@ synapse:
|
||||||
restic:
|
restic:
|
||||||
repo_url: ENC[AES256_GCM,data:ZcBMqwEsyc7zyEftJZj4XkKBzUHwlqd6cjX8xVDn9m26jBL7aP5atpnXDRE9FXY4CuAllFyQZyAOQ2L61Nfx+iplL2ADbSoH,iv:fhNODiyoOlZEqYR2O/GsH2IWTPDr3rXSJgWC/EFDLSA=,tag:nZdKKnpiszSiXxdZI1KQ/A==,type:str]
|
repo_url: ENC[AES256_GCM,data:ZcBMqwEsyc7zyEftJZj4XkKBzUHwlqd6cjX8xVDn9m26jBL7aP5atpnXDRE9FXY4CuAllFyQZyAOQ2L61Nfx+iplL2ADbSoH,iv:fhNODiyoOlZEqYR2O/GsH2IWTPDr3rXSJgWC/EFDLSA=,tag:nZdKKnpiszSiXxdZI1KQ/A==,type:str]
|
||||||
repo_password: ENC[AES256_GCM,data:9YDOz1tiyykz6zSXboWtIg==,iv:j96mRLXGuD4NZcC0Nv1yXFbtOlr6UborqclefZ7J94w=,tag:MqhSewK2NuckTJBf7xu+lA==,type:str]
|
repo_password: ENC[AES256_GCM,data:9YDOz1tiyykz6zSXboWtIg==,iv:j96mRLXGuD4NZcC0Nv1yXFbtOlr6UborqclefZ7J94w=,tag:MqhSewK2NuckTJBf7xu+lA==,type:str]
|
||||||
|
miniflux:
|
||||||
|
oauth2_secret: ENC[AES256_GCM,data:/WtZemrdKU8bQbxzrAn437uqoJSO+yZSUDCnxovXV0HFZYQvAn2rbMrgOdoc1OuP,iv:xENKuGDYS1ctnO/WkGv1TxjtQYZ8p64Ik/lMIIam4Q0=,tag:RbAA0LUmsAQDqEM5+a2quQ==,type:str]
|
||||||
|
hedgedoc:
|
||||||
|
client_secret: ENC[AES256_GCM,data:J6lRBM7V6F+gPYVyEbOzsFUQe8+3ggP0r58c655DNt7TGgKGdq95pRvLaghMmBCc,iv:i+eLYwnmG1/bKtad2iM2pwEAC3GZLNaKS5ldbubRvyY=,tag:yxaug6YdYo8RR3YOyHd/iA==,type:str]
|
||||||
|
forgejo:
|
||||||
|
client_secret: ENC[AES256_GCM,data:5OXhaGzBCbge2tvTaU4ry6/KoavQeYJ45EuakCQJlxb5gMXjRK/s+feF25YJSr2f,iv:TT8j+ciKeSQCZzu1E7D70hWNFpn0cGiomz7jURXjavc=,tag:JVJR033Pc2vaLudaovkl8w==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
|
@ -29,8 +35,8 @@ sops:
|
||||||
RzBMVDNjS29SUkdRK3dIV01sU0hYR3cK1SbvKAM6Gpsffv3HIi/WtWnCZUBic0AT
|
RzBMVDNjS29SUkdRK3dIV01sU0hYR3cK1SbvKAM6Gpsffv3HIi/WtWnCZUBic0AT
|
||||||
ZRv4pvJBx1oxWsKIHW0t6VrqWMQ+suup8p6dW+h5HE8Z4ciIMrXLEg==
|
ZRv4pvJBx1oxWsKIHW0t6VrqWMQ+suup8p6dW+h5HE8Z4ciIMrXLEg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2024-12-03T07:38:24Z"
|
lastmodified: "2024-12-04T05:07:32Z"
|
||||||
mac: ENC[AES256_GCM,data:KMKdwgu9+3DjG1lrQYQEz/jYWsHUBK6RgHRyRKzWG0jTDg30owRpCgnSnX5gHzygmSYSnVRtcTOWzqm5bI7/KJkXBivaqkLqCh6EHnTj+pnAHmeEOAjoOVLOMSCEYvHMf/EuJIL199Hf2G12LtulDJV7Wi5r5Jy8L9odVlYuM9g=,iv:WTeqWdIztScZnXc2hzI7JHO/4ySgqycOp2eN9EPTQpw=,tag:lTMrE5JVVFCIDehXCxJZoQ==,type:str]
|
mac: ENC[AES256_GCM,data:hD7645epMVYHU6K1AZsHu+fp/PMIqqiZpv7K4Vxzo84slzn0CfZSYaVaYxKNGjOIgEGN9D2FFmq9WL6ChMskMfqqafY7qDpSQqFp9TUwb5jN34XcQg9vplfNw+lMqsnDCt1HENWErRnlDxTI2ctSEcx3UKGBOQ3ttLzUIySdnFY=,iv:reOsqvc8E3l8yxb5gVcqF/rU2o2yKmaUyGNRNT+Skx8=,tag:eBoV8G+X0cPs3Q1xAuv55w==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.9.1
|
version: 3.9.1
|
||||||
|
|
113
machines/biotite/services/forgejo.nix
Normal file
113
machines/biotite/services/forgejo.nix
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
my-lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib) getExe;
|
||||||
|
inherit (my-lib.settings) idpUrl forgejoDomain forgejoGitDomain;
|
||||||
|
settings = {
|
||||||
|
service.DISABLE_REGISTRATION = true;
|
||||||
|
server = {
|
||||||
|
DOMAIN = forgejoDomain;
|
||||||
|
ROOT_URL = "https://${forgejoDomain}";
|
||||||
|
HTTP_ADDR = "/var/run/forgejo/forgejo.sock";
|
||||||
|
START_SSH_SERVER = false;
|
||||||
|
SSH_USER = config.services.forgejo.user;
|
||||||
|
SSH_DOMAIN = forgejoGitDomain;
|
||||||
|
SSH_PORT = 22;
|
||||||
|
PROTOCOL = "http+unix";
|
||||||
|
LFS_MAX_FILE_SIZE = 10737418240;
|
||||||
|
LANDING_PAGE = "/explore/repos";
|
||||||
|
};
|
||||||
|
repository = {
|
||||||
|
ENABLE_PUSH_CREATE_USER = true;
|
||||||
|
};
|
||||||
|
service = {
|
||||||
|
ENABLE_BASIC_AUTHENTICATION = false;
|
||||||
|
};
|
||||||
|
oauth2 = {
|
||||||
|
ENABLED = false; # Disable forgejo as oauth2 provider
|
||||||
|
};
|
||||||
|
oauth2_client = {
|
||||||
|
ACCOUNT_LINKING = "auto";
|
||||||
|
USERNAME = "email";
|
||||||
|
ENABLE_AUTO_REGISTRATION = true;
|
||||||
|
UPDATE_AVATAR = false;
|
||||||
|
OPENID_CONNECT_SCOPES = "openid profile email groups";
|
||||||
|
};
|
||||||
|
other = {
|
||||||
|
SHOW_FOOTER_VERSION = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sops.secrets."forgejo/client_secret" = { };
|
||||||
|
sops.templates."forgejo/env" = {
|
||||||
|
content = ''
|
||||||
|
CLIENT_SECRET=${config.sops.placeholder."forgejo/client_secret"}
|
||||||
|
'';
|
||||||
|
owner = config.systemd.services.forgejo.serviceConfig.User;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.forgejo = {
|
||||||
|
enable = true;
|
||||||
|
inherit settings;
|
||||||
|
# Use cutting edge instead of lts
|
||||||
|
package = pkgs.forgejo;
|
||||||
|
# repositoryRoot = "/mnt/storage/forgejo/repositories";
|
||||||
|
lfs = {
|
||||||
|
enable = true;
|
||||||
|
# contentDir = "/mnt/storage/forgejo/lfs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.forgejo = {
|
||||||
|
serviceConfig = {
|
||||||
|
EnvironmentFile = config.sops.templates."forgejo/env".path;
|
||||||
|
preStart =
|
||||||
|
let
|
||||||
|
providerName = "kanidm";
|
||||||
|
args = lib.concatStringsSep " " [
|
||||||
|
"--name ${providerName}"
|
||||||
|
"--provider openidConnect"
|
||||||
|
"--key forgejo"
|
||||||
|
"--secret $CLIENT_SECRET"
|
||||||
|
"--icon-url ${idpUrl}/pkg/img/favicon.png"
|
||||||
|
"--group-claim-name forgejo_role --admin-group Admin"
|
||||||
|
];
|
||||||
|
exe = getExe config.services.forgejo.package;
|
||||||
|
in
|
||||||
|
''
|
||||||
|
provider_id=$(${exe} admin auth list | ${pkgs.gnugrep}/bin/grep -w '${providerName}' | cut -f1)
|
||||||
|
if [[ -z "$provider_id" ]]; then
|
||||||
|
${exe} admin auth add-oauth ${args}
|
||||||
|
else
|
||||||
|
${exe} admin auth update-oauth --id "$provider_id" ${args}
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.git = {
|
||||||
|
isSystemUser = true;
|
||||||
|
useDefaultShell = true;
|
||||||
|
group = "git";
|
||||||
|
extraGroups = [ "forgejo" ];
|
||||||
|
};
|
||||||
|
users.groups.git = { };
|
||||||
|
|
||||||
|
services.caddy = {
|
||||||
|
virtualHosts."https://${forgejoDomain}".extraConfig = with settings; ''
|
||||||
|
${
|
||||||
|
if server.PROTOCOL == "http+unix" then
|
||||||
|
"reverse_proxy unix/${server.HTTP_ADDR}"
|
||||||
|
else
|
||||||
|
"reverse_proxy http://${server.HTTP_ADDR}:${toString server.HTTP_PORT}"
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
users.users.caddy.extraGroups = lib.optional (settings.server.PROTOCOL == "http+unix") "forgejo";
|
||||||
|
}
|
44
machines/biotite/services/hedgedoc.nix
Normal file
44
machines/biotite/services/hedgedoc.nix
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{ config, my-lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (my-lib.settings) hedgedocDomain idpUrl;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sops.secrets."hedgedoc/client_secret" = { };
|
||||||
|
sops.templates."hedgedoc/env" = {
|
||||||
|
content = ''
|
||||||
|
CMD_OAUTH2_CLIENT_SECRET=${config.sops.placeholder."hedgedoc/client_secret"}
|
||||||
|
'';
|
||||||
|
owner = config.systemd.services.hedgedoc.serviceConfig.User;
|
||||||
|
};
|
||||||
|
services.hedgedoc = {
|
||||||
|
enable = true;
|
||||||
|
environmentFile = config.sops.templates."hedgedoc/env".path;
|
||||||
|
settings = {
|
||||||
|
domain = hedgedocDomain;
|
||||||
|
protocolUseSSL = true; # use SSL for resources
|
||||||
|
path = "/run/hedgedoc/hedgedoc.sock";
|
||||||
|
email = false;
|
||||||
|
allowEmailRegister = false;
|
||||||
|
oauth2 = {
|
||||||
|
baseURL = "${idpUrl}/oauth2/openid/hedgedoc";
|
||||||
|
authorizationURL = "${idpUrl}/ui/oauth2";
|
||||||
|
tokenURL = "${idpUrl}/oauth2/token";
|
||||||
|
userProfileURL = "${idpUrl}/oauth2/openid/hedgedoc/userinfo";
|
||||||
|
userProfileEmailAttr = "email";
|
||||||
|
userProfileUsernameAttr = "name";
|
||||||
|
userProfileDisplayNameAttr = "preferred_name";
|
||||||
|
scope = "openid email profile";
|
||||||
|
clientID = "hedgedoc";
|
||||||
|
};
|
||||||
|
allowAnonymous = false;
|
||||||
|
defaultPermission = "private";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.caddy = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts."https://${hedgedocDomain}".extraConfig = ''
|
||||||
|
reverse_proxy unix/${config.services.hedgedoc.settings.path}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
users.users.caddy.extraGroups = [ "hedgedoc" ];
|
||||||
|
}
|
35
machines/biotite/services/miniflux.nix
Normal file
35
machines/biotite/services/miniflux.nix
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
{ config, my-lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (my-lib.settings) idpUrl minifluxUrl;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sops = {
|
||||||
|
secrets."miniflux/oauth2_secret" = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
services.miniflux = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
LOG_LEVEL = "debug";
|
||||||
|
LISTEN_ADDR = "127.0.0.1:58173";
|
||||||
|
BASE_URL = "https://rss.xiny.li/";
|
||||||
|
OAUTH2_PROVIDER = "oidc";
|
||||||
|
OAUTH2_CLIENT_ID = "miniflux";
|
||||||
|
OAUTH2_CLIENT_SECRET_FILE = "%d/oauth2_secret";
|
||||||
|
OAUTH2_REDIRECT_URL = "${minifluxUrl}/oauth2/oidc/callback";
|
||||||
|
OAUTH2_OIDC_DISCOVERY_ENDPOINT = "${idpUrl}/oauth2/openid/miniflux";
|
||||||
|
OAUTH2_USER_CREATION = 1;
|
||||||
|
CREATE_ADMIN = 0;
|
||||||
|
};
|
||||||
|
createDatabaseLocally = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.miniflux.serviceConfig.LoadCredential = [
|
||||||
|
"oauth2_secret:${config.sops.secrets."miniflux/oauth2_secret".path}"
|
||||||
|
];
|
||||||
|
|
||||||
|
services.caddy.virtualHosts.${minifluxUrl}.extraConfig = ''
|
||||||
|
reverse_proxy ${config.services.miniflux.config.LISTEN_ADDR}
|
||||||
|
'';
|
||||||
|
|
||||||
|
}
|
25
machines/biotite/services/vaultwarden.nix
Normal file
25
machines/biotite/services/vaultwarden.nix
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{ config, my-lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (my-lib.settings) vaultwardenUrl;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.vaultwarden = {
|
||||||
|
enable = true;
|
||||||
|
dbBackend = "sqlite";
|
||||||
|
config = {
|
||||||
|
DOMAIN = "${vaultwardenUrl}";
|
||||||
|
SIGNUPS_ALLOWED = false;
|
||||||
|
|
||||||
|
ROCKET_ADDRESS = "127.0.0.1";
|
||||||
|
ROCKET_PORT = 8222;
|
||||||
|
|
||||||
|
ROCKET_LOG = "normal";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.caddy = {
|
||||||
|
virtualHosts.${vaultwardenUrl}.extraConfig = with config.services.vaultwarden.config; ''
|
||||||
|
reverse_proxy ${ROCKET_ADDRESS}:${toString ROCKET_PORT}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
|
@ -21,12 +21,6 @@
|
||||||
gts_env = {
|
gts_env = {
|
||||||
owner = "gotosocial";
|
owner = "gotosocial";
|
||||||
};
|
};
|
||||||
hedgedoc_env = {
|
|
||||||
owner = "hedgedoc";
|
|
||||||
};
|
|
||||||
grafana_oauth_secret = {
|
|
||||||
owner = "grafana";
|
|
||||||
};
|
|
||||||
"miniflux/oauth2_secret" = {
|
"miniflux/oauth2_secret" = {
|
||||||
owner = "root";
|
owner = "root";
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
{ config, lib, ... }:
|
{ my-lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (my-lib.settings)
|
||||||
|
gotosocialUrl
|
||||||
|
minifluxUrl
|
||||||
|
hedgedocDomain
|
||||||
|
forgejoDomain
|
||||||
|
;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
services.kanidm.provision = {
|
services.kanidm.provision = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -76,8 +84,8 @@
|
||||||
systems.oauth2 = {
|
systems.oauth2 = {
|
||||||
forgejo = {
|
forgejo = {
|
||||||
displayName = "ForgeJo";
|
displayName = "ForgeJo";
|
||||||
originUrl = "https://git.xinyang.life/user/oauth2/kanidm/callback";
|
originUrl = "https://${forgejoDomain}/user/oauth2/kanidm/callback";
|
||||||
originLanding = "https://git.xinyang.life/user/oauth2/kanidm";
|
originLanding = "https://${forgejoDomain}/user/oauth2/kanidm";
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
scopeMaps = {
|
scopeMaps = {
|
||||||
forgejo-access = [
|
forgejo-access = [
|
||||||
|
@ -113,8 +121,8 @@
|
||||||
};
|
};
|
||||||
gotosocial = {
|
gotosocial = {
|
||||||
displayName = "GoToSocial";
|
displayName = "GoToSocial";
|
||||||
originUrl = "https://gts.xiny.li/auth/callback";
|
originUrl = "${gotosocialUrl}/auth/callback";
|
||||||
originLanding = "https://gts.xiny.li/auth/callback";
|
originLanding = "${gotosocialUrl}/auth/callback";
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
scopeMaps = {
|
scopeMaps = {
|
||||||
gts-users = [
|
gts-users = [
|
||||||
|
@ -150,8 +158,8 @@
|
||||||
|
|
||||||
hedgedoc = {
|
hedgedoc = {
|
||||||
displayName = "HedgeDoc";
|
displayName = "HedgeDoc";
|
||||||
originUrl = "https://docs.xinyang.life/auth/oauth2/callback";
|
originUrl = "https://${hedgedocDomain}/auth/oauth2/callback";
|
||||||
originLanding = "https://docs.xinyang.life/auth/oauth2";
|
originLanding = "https://${hedgedocDomain}/auth/oauth2";
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
scopeMaps = {
|
scopeMaps = {
|
||||||
hedgedoc-users = [
|
hedgedoc-users = [
|
||||||
|
@ -180,9 +188,8 @@
|
||||||
};
|
};
|
||||||
miniflux = {
|
miniflux = {
|
||||||
displayName = "Miniflux";
|
displayName = "Miniflux";
|
||||||
originUrl = "https://rss.xinyang.life/oauth2/oidc/callback";
|
originUrl = "${minifluxUrl}/oauth2/oidc/callback";
|
||||||
|
originLanding = "${minifluxUrl}/oauth2/oidc/redirect";
|
||||||
originLanding = "https://rss.xinyang.life/oauth2/oidc/redirect";
|
|
||||||
scopeMaps = {
|
scopeMaps = {
|
||||||
miniflux-users = [
|
miniflux-users = [
|
||||||
"openid"
|
"openid"
|
||||||
|
|
|
@ -23,26 +23,6 @@ in
|
||||||
8448
|
8448
|
||||||
];
|
];
|
||||||
|
|
||||||
custom.vaultwarden = {
|
|
||||||
enable = true;
|
|
||||||
domain = "vaultwarden.xinyang.life";
|
|
||||||
};
|
|
||||||
|
|
||||||
custom.hedgedoc = {
|
|
||||||
enable = true;
|
|
||||||
caddy = true;
|
|
||||||
domain = "docs.xinyang.life";
|
|
||||||
mediaPath = "/mnt/storage/hedgedoc";
|
|
||||||
oidc = {
|
|
||||||
enable = true;
|
|
||||||
baseURL = "https://auth.xinyang.life/oauth2/openid/hedgedoc";
|
|
||||||
authorizationURL = "https://auth.xinyang.life/ui/oauth2";
|
|
||||||
tokenURL = "https://auth.xinyang.life/oauth2/token";
|
|
||||||
userProfileURL = "https://auth.xinyang.life/oauth2/openid/hedgedoc/userinfo";
|
|
||||||
};
|
|
||||||
environmentFile = config.sops.secrets.hedgedoc_env.path;
|
|
||||||
};
|
|
||||||
|
|
||||||
custom.monitoring = {
|
custom.monitoring = {
|
||||||
promtail.enable = true;
|
promtail.enable = true;
|
||||||
};
|
};
|
||||||
|
@ -92,40 +72,6 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
custom.miniflux = {
|
|
||||||
enable = true;
|
|
||||||
environment = {
|
|
||||||
LOG_LEVEL = "debug";
|
|
||||||
LISTEN_ADDR = "127.0.0.1:58173";
|
|
||||||
BASE_URL = "https://rss.xinyang.life/";
|
|
||||||
OAUTH2_PROVIDER = "oidc";
|
|
||||||
OAUTH2_CLIENT_ID = "miniflux";
|
|
||||||
OAUTH2_REDIRECT_URL = "https://rss.xinyang.life/oauth2/oidc/callback";
|
|
||||||
OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://auth.xinyang.life/oauth2/openid/miniflux";
|
|
||||||
OAUTH2_USER_CREATION = 1;
|
|
||||||
};
|
|
||||||
oauth2SecretFile = config.sops.secrets."miniflux/oauth2_secret".path;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.matrix-conduit = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.matrix-conduit;
|
|
||||||
settings.global = {
|
|
||||||
server_name = "xinyang.life";
|
|
||||||
port = 6167;
|
|
||||||
# database_path = "/var/lib/matrix-conduit/";
|
|
||||||
max_concurrent_requests = 100;
|
|
||||||
log = "info";
|
|
||||||
database_backend = "rocksdb";
|
|
||||||
allow_registration = false;
|
|
||||||
|
|
||||||
well_known = {
|
|
||||||
client = "https://msg.xinyang.life";
|
|
||||||
server = "msg.xinyang.life:443";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.conduit = {
|
users.users.conduit = {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
group = "conduit";
|
group = "conduit";
|
||||||
|
@ -150,111 +96,6 @@ in
|
||||||
environmentFile = config.sops.secrets.gts_env.path;
|
environmentFile = config.sops.secrets.gts_env.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.forgejo = {
|
|
||||||
enable = true;
|
|
||||||
# Use cutting edge instead of lts
|
|
||||||
package = pkgs.forgejo;
|
|
||||||
repositoryRoot = "/mnt/storage/forgejo/repositories";
|
|
||||||
lfs = {
|
|
||||||
enable = true;
|
|
||||||
contentDir = "/mnt/storage/forgejo/lfs";
|
|
||||||
};
|
|
||||||
settings = {
|
|
||||||
service.DISABLE_REGISTRATION = true;
|
|
||||||
server = {
|
|
||||||
ROOT_URL = "https://git.xinyang.life/";
|
|
||||||
START_SSH_SERVER = false;
|
|
||||||
SSH_USER = config.services.forgejo.user;
|
|
||||||
SSH_DOMAIN = "ssh.xinyang.life";
|
|
||||||
SSH_PORT = 22;
|
|
||||||
LFS_MAX_FILE_SIZE = 10737418240;
|
|
||||||
LANDING_PAGE = "/explore/repos";
|
|
||||||
};
|
|
||||||
repository = {
|
|
||||||
ENABLE_PUSH_CREATE_USER = true;
|
|
||||||
};
|
|
||||||
service = {
|
|
||||||
ENABLE_BASIC_AUTHENTICATION = false;
|
|
||||||
};
|
|
||||||
oauth2 = {
|
|
||||||
ENABLED = false; # Disable forgejo as oauth2 provider
|
|
||||||
};
|
|
||||||
oauth2_client = {
|
|
||||||
ACCOUNT_LINKING = "auto";
|
|
||||||
USERNAME = "email";
|
|
||||||
ENABLE_AUTO_REGISTRATION = true;
|
|
||||||
UPDATE_AVATAR = false;
|
|
||||||
OPENID_CONNECT_SCOPES = "openid profile email groups";
|
|
||||||
};
|
|
||||||
other = {
|
|
||||||
SHOW_FOOTER_VERSION = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.forgejo = {
|
|
||||||
serviceConfig = {
|
|
||||||
EnvironmentFile = config.sops.secrets."forgejo/env".path;
|
|
||||||
ExecStartPost = ''
|
|
||||||
${lib.getExe config.services.forgejo.package} admin auth update-oauth \
|
|
||||||
--id 1 \
|
|
||||||
--name kanidm \
|
|
||||||
--provider openidConnect \
|
|
||||||
--key forgejo \
|
|
||||||
--secret $CLIENT_SECRET \
|
|
||||||
--icon-url https://auth.xinyang.life/pkg/img/favicon.png \
|
|
||||||
--group-claim-name forgejo_role --admin-group Admin
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.grafana = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
server = {
|
|
||||||
http_addr = "127.0.0.1";
|
|
||||||
http_port = 3003;
|
|
||||||
root_url = "https://grafana.xinyang.life";
|
|
||||||
domain = "grafana.xinyang.life";
|
|
||||||
};
|
|
||||||
"auth.generic_oauth" = {
|
|
||||||
enabled = true;
|
|
||||||
name = "Kanidm";
|
|
||||||
client_id = "grafana";
|
|
||||||
scopes = "openid,profile,email,groups";
|
|
||||||
auth_url = "https://auth.xinyang.life/ui/oauth2";
|
|
||||||
token_url = "https://auth.xinyang.life/oauth2/token";
|
|
||||||
api_url = "https://auth.xinyang.life/oauth2/openid/grafana/userinfo";
|
|
||||||
use_pkce = true;
|
|
||||||
use_refresh_token = true;
|
|
||||||
allow_sign_up = true;
|
|
||||||
login_attribute_path = "preferred_username";
|
|
||||||
groups_attribute_path = "groups";
|
|
||||||
role_attribute_path = "contains(grafana_role[*], 'GrafanaAdmin') && 'GrafanaAdmin' || contains(grafana_role[*], 'Admin') && 'Admin' || contains(grafana_role[*], 'Editor') && 'Editor' || 'Viewer'";
|
|
||||||
allow_assign_grafana_admin = true;
|
|
||||||
auto_login = true;
|
|
||||||
};
|
|
||||||
"auth" = {
|
|
||||||
disable_login_form = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.grafana.serviceConfig.EnvironmentFile =
|
|
||||||
config.sops.secrets.grafana_oauth_secret.path;
|
|
||||||
|
|
||||||
users.users.git = {
|
|
||||||
isSystemUser = true;
|
|
||||||
useDefaultShell = true;
|
|
||||||
group = "git";
|
|
||||||
extraGroups = [ "forgejo" ];
|
|
||||||
};
|
|
||||||
users.groups.git = { };
|
|
||||||
|
|
||||||
users.users = {
|
|
||||||
${config.services.caddy.user}.extraGroups = [ config.services.ntfy-sh.group ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.caddy = {
|
services.caddy = {
|
||||||
enable = true;
|
enable = true;
|
||||||
virtualHosts."xinyang.life:443".extraConfig = ''
|
virtualHosts."xinyang.life:443".extraConfig = ''
|
||||||
|
@ -265,12 +106,6 @@ in
|
||||||
flush_interval -1
|
flush_interval -1
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
virtualHosts."https://msg.xinyang.life:443".extraConfig = ''
|
|
||||||
reverse_proxy /_matrix/* localhost:6167
|
|
||||||
'';
|
|
||||||
virtualHosts."https://git.xinyang.life:443".extraConfig = ''
|
|
||||||
reverse_proxy http://${config.services.gitea.settings.server.DOMAIN}:${toString config.services.gitea.settings.server.HTTP_PORT}
|
|
||||||
'';
|
|
||||||
|
|
||||||
virtualHosts."http://auth.xinyang.life:80".extraConfig = ''
|
virtualHosts."http://auth.xinyang.life:80".extraConfig = ''
|
||||||
reverse_proxy ${config.security.acme.certs."auth.xinyang.life".listenHTTP}
|
reverse_proxy ${config.security.acme.certs."auth.xinyang.life".listenHTTP}
|
||||||
|
@ -285,10 +120,6 @@ in
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
virtualHosts."https://rss.xinyang.life".extraConfig = ''
|
|
||||||
reverse_proxy ${config.custom.miniflux.environment.LISTEN_ADDR}
|
|
||||||
'';
|
|
||||||
|
|
||||||
virtualHosts."https://ntfy.xinyang.life".extraConfig = ''
|
virtualHosts."https://ntfy.xinyang.life".extraConfig = ''
|
||||||
reverse_proxy unix/${config.services.ntfy-sh.settings.listen-unix}
|
reverse_proxy unix/${config.services.ntfy-sh.settings.listen-unix}
|
||||||
@httpget {
|
@httpget {
|
||||||
|
@ -298,13 +129,5 @@ in
|
||||||
}
|
}
|
||||||
redir @httpget https://{host}{uri}
|
redir @httpget https://{host}{uri}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
virtualHosts."https://grafana.xinyang.life".extraConfig =
|
|
||||||
let
|
|
||||||
grafanaSettings = config.services.grafana.settings.server;
|
|
||||||
in
|
|
||||||
''
|
|
||||||
reverse_proxy http://${grafanaSettings.http_addr}:${toString grafanaSettings.http_port}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,16 +73,16 @@ with my-lib;
|
||||||
{
|
{
|
||||||
inherit passwordFile;
|
inherit passwordFile;
|
||||||
name = "gotosocial";
|
name = "gotosocial";
|
||||||
address = "xinyang.life";
|
address = "gts.xiny.li";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
inherit passwordFile;
|
inherit passwordFile;
|
||||||
name = "miniflux";
|
name = "miniflux";
|
||||||
address = "rss.xinyang.life";
|
address = "rss.xiny.li";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "ntfy";
|
name = "ntfy";
|
||||||
address = "ntfy.xinyang.life";
|
address = "ntfy.xiny.li";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "grafana-eu";
|
name = "grafana-eu";
|
||||||
|
|
|
@ -7,15 +7,10 @@
|
||||||
./common-settings/mainland.nix
|
./common-settings/mainland.nix
|
||||||
./disk-partitions
|
./disk-partitions
|
||||||
./restic.nix
|
./restic.nix
|
||||||
./vaultwarden.nix
|
|
||||||
./monitor
|
./monitor
|
||||||
./hedgedoc.nix
|
|
||||||
./sing-box.nix
|
|
||||||
./kanidm-client.nix
|
./kanidm-client.nix
|
||||||
./ssh-tpm-agent.nix # FIXME: Waiting for upstream merge
|
# ./ssh-tpm-agent.nix # FIXME: Waiting for upstream merge
|
||||||
./forgejo-actions-runner.nix
|
./forgejo-actions-runner.nix
|
||||||
./oidc-agent.nix
|
|
||||||
./miniflux.nix
|
|
||||||
./immich.nix
|
./immich.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.custom.hedgedoc;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
custom.hedgedoc = {
|
|
||||||
enable = mkEnableOption "HedgeDoc Markdown Editor";
|
|
||||||
domain = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "docs.example.com";
|
|
||||||
description = "Domain name of the HedgeDoc server";
|
|
||||||
};
|
|
||||||
caddy = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "Enable Caddy as reverse proxy";
|
|
||||||
};
|
|
||||||
mediaPath = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = /var/lib/hedgedoc/uploads;
|
|
||||||
description = "Directory for storing medias";
|
|
||||||
};
|
|
||||||
oidc = {
|
|
||||||
enable = mkEnableOption "OIDC support for HedgeDoc";
|
|
||||||
baseURL = mkOption { type = types.str; };
|
|
||||||
authorizationURL = mkOption { type = types.str; };
|
|
||||||
tokenURL = mkOption { type = types.str; };
|
|
||||||
userProfileURL = mkOption { type = types.str; };
|
|
||||||
};
|
|
||||||
environmentFile = mkOption { type = types.path; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
services.hedgedoc = {
|
|
||||||
enable = true;
|
|
||||||
environmentFile = cfg.environmentFile;
|
|
||||||
settings = {
|
|
||||||
domain = cfg.domain;
|
|
||||||
protocolUseSSL = cfg.caddy;
|
|
||||||
uploadsPath = cfg.mediaPath;
|
|
||||||
path = "/run/hedgedoc/hedgedoc.sock";
|
|
||||||
email = false;
|
|
||||||
allowEmailRegister = false;
|
|
||||||
oauth2 = mkIf cfg.oidc.enable {
|
|
||||||
baseURL = cfg.oidc.baseURL;
|
|
||||||
authorizationURL = cfg.oidc.authorizationURL;
|
|
||||||
tokenURL = cfg.oidc.tokenURL;
|
|
||||||
userProfileURL = cfg.oidc.userProfileURL;
|
|
||||||
userProfileEmailAttr = "email";
|
|
||||||
userProfileUsernameAttr = "name";
|
|
||||||
userProfileDisplayNameAttr = "preferred_name";
|
|
||||||
scope = "openid email profile";
|
|
||||||
clientID = "$HEDGEDOC_CLIENT_ID";
|
|
||||||
clientSecret = "$HEDGEDOC_CLIENT_SECRET";
|
|
||||||
};
|
|
||||||
allowAnonymous = false;
|
|
||||||
defaultPermission = "private";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
services.caddy = mkIf cfg.caddy {
|
|
||||||
enable = true;
|
|
||||||
virtualHosts."https://${cfg.domain}".extraConfig = ''
|
|
||||||
reverse_proxy unix/${config.services.hedgedoc.settings.path}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
users.users.caddy.extraGroups = mkIf cfg.caddy [ "hedgedoc" ];
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.custom.sing-box-server;
|
|
||||||
|
|
||||||
secretFileType = lib.types.submodule { _secret = lib.types.path; };
|
|
||||||
singTls = {
|
|
||||||
enabled = true;
|
|
||||||
server_name = config.deployment.targetHost;
|
|
||||||
key_path = config.security.acme.certs.${config.deployment.targetHost}.directory + "/key.pem";
|
|
||||||
certificate_path =
|
|
||||||
config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
enable = lib.mkEnableOption "sing-box proxy server";
|
|
||||||
users = lib.types.listOf lib.types.submodule {
|
|
||||||
name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "proxy";
|
|
||||||
};
|
|
||||||
password = lib.mkOption { type = secretFileType; };
|
|
||||||
uuid = lib.mkOption { type = secretFileType; };
|
|
||||||
};
|
|
||||||
wgOut = {
|
|
||||||
privKeyFile = lib.mkOption { type = lib.types.path; };
|
|
||||||
pubkey = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
inbounds = {
|
|
||||||
trojan = {
|
|
||||||
enable = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
tuic = {
|
|
||||||
enable = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
ports = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.int;
|
|
||||||
default = lib.range 6311 6313;
|
|
||||||
};
|
|
||||||
directPorts = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.int;
|
|
||||||
default = [ 6314 ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.sing-box = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
dns = {
|
|
||||||
servers = [
|
|
||||||
{
|
|
||||||
address = "1.1.1.1";
|
|
||||||
detour = "wg-out";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
inbounds =
|
|
||||||
[
|
|
||||||
# TODO: Trojan and tuic enable
|
|
||||||
{
|
|
||||||
tag = "trojan-in";
|
|
||||||
type = "trojan";
|
|
||||||
listen = "::";
|
|
||||||
listen_port = 8080;
|
|
||||||
users = map (u: removeAttrs u [ "uuid" ]) cfg.users;
|
|
||||||
tls = singTls;
|
|
||||||
}
|
|
||||||
]
|
|
||||||
++ lib.forEach (cfg.tuic.ports ++ cfg.tuic.directPorts) (port: {
|
|
||||||
tag = "tuic-in" + toString port;
|
|
||||||
type = "tuic";
|
|
||||||
listen = "::";
|
|
||||||
listen_port = port;
|
|
||||||
congestion_control = "bbr";
|
|
||||||
users = cfg.users;
|
|
||||||
tls = singTls;
|
|
||||||
});
|
|
||||||
outbounds = [
|
|
||||||
{
|
|
||||||
type = "wireguard";
|
|
||||||
tag = "wg-out";
|
|
||||||
private_key = cfg.wgOut.privKeyFile;
|
|
||||||
local_address = [
|
|
||||||
"172.16.0.2/32"
|
|
||||||
"2606:4700:110:82ed:a443:3c62:6cbc:b59b/128"
|
|
||||||
];
|
|
||||||
peers = [
|
|
||||||
{
|
|
||||||
public_key = cfg.wgOut.pubkey;
|
|
||||||
allowed_ips = [
|
|
||||||
"0.0.0.0/0"
|
|
||||||
"::/0"
|
|
||||||
];
|
|
||||||
server = "162.159.192.1";
|
|
||||||
server_port = 500;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
type = "direct";
|
|
||||||
tag = "direct-out";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
type = "dns";
|
|
||||||
tag = "dns-out";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
route = {
|
|
||||||
rules =
|
|
||||||
[
|
|
||||||
{
|
|
||||||
outbound = "dns-out";
|
|
||||||
protocol = "dns";
|
|
||||||
}
|
|
||||||
]
|
|
||||||
++ lib.forEach cfg.tuic.directPorts (port: {
|
|
||||||
inbound = "tuic-in" + toString port;
|
|
||||||
outbound = "direct-out";
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -59,8 +59,6 @@ in
|
||||||
PasswordAuthentication = false;
|
PasswordAuthentication = false;
|
||||||
KbdInteractiveAuthentication = false;
|
KbdInteractiveAuthentication = false;
|
||||||
PermitRootLogin = lib.mkForce "no";
|
PermitRootLogin = lib.mkForce "no";
|
||||||
GSSAPIAuthentication = "no";
|
|
||||||
KerberosAuthentication = "no";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
inherit (lib)
|
|
||||||
mkEnableOption
|
|
||||||
mkPackageOption
|
|
||||||
mkOption
|
|
||||||
types
|
|
||||||
literalExpression
|
|
||||||
mkIf
|
|
||||||
mkDefault
|
|
||||||
;
|
|
||||||
cfg = config.custom.miniflux;
|
|
||||||
|
|
||||||
defaultAddress = "localhost:8080";
|
|
||||||
|
|
||||||
pgbin = "${config.services.postgresql.package}/bin";
|
|
||||||
preStart = pkgs.writeScript "miniflux-pre-start" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
${pgbin}/psql "miniflux" -c "CREATE EXTENSION IF NOT EXISTS hstore"
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
custom.miniflux = {
|
|
||||||
enable = mkEnableOption "miniflux";
|
|
||||||
|
|
||||||
package = mkPackageOption pkgs "miniflux" { };
|
|
||||||
|
|
||||||
oauth2SecretFile = mkOption { type = types.path; };
|
|
||||||
|
|
||||||
environment = mkOption {
|
|
||||||
type =
|
|
||||||
with types;
|
|
||||||
attrsOf (oneOf [
|
|
||||||
int
|
|
||||||
str
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
createDatabaseLocally = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether a PostgreSQL database should be automatically created and
|
|
||||||
configured on the local host. If set to `false`, you need provision a
|
|
||||||
database yourself and make sure to create the hstore extension in it.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.miniflux.enable = false;
|
|
||||||
custom.miniflux.environment = {
|
|
||||||
LISTEN_ADDR = mkDefault defaultAddress;
|
|
||||||
RUN_MIGRATIONS = mkDefault 1;
|
|
||||||
DATABASE_URL = lib.mkIf cfg.createDatabaseLocally "user=miniflux host=/run/postgresql dbname=miniflux";
|
|
||||||
OAUTH2_CLIENT_SECRET_FILE = "%d/oauth2_secret";
|
|
||||||
WATCHDOG = mkDefault 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.postgresql = lib.mkIf cfg.createDatabaseLocally {
|
|
||||||
enable = true;
|
|
||||||
ensureUsers = [
|
|
||||||
{
|
|
||||||
name = "miniflux";
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
ensureDatabases = [ "miniflux" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.miniflux-dbsetup = lib.mkIf cfg.createDatabaseLocally {
|
|
||||||
description = "Miniflux database setup";
|
|
||||||
requires = [ "postgresql.service" ];
|
|
||||||
after = [
|
|
||||||
"network.target"
|
|
||||||
"postgresql.service"
|
|
||||||
];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
User = config.services.postgresql.superUser;
|
|
||||||
ExecStart = preStart;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.miniflux = {
|
|
||||||
description = "Miniflux service";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
requires = lib.optional cfg.createDatabaseLocally "miniflux-dbsetup.service";
|
|
||||||
after =
|
|
||||||
[ "network.target" ]
|
|
||||||
++ lib.optionals cfg.createDatabaseLocally [
|
|
||||||
"postgresql.service"
|
|
||||||
"miniflux-dbsetup.service"
|
|
||||||
];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "notify";
|
|
||||||
ExecStart = lib.getExe cfg.package;
|
|
||||||
User = "miniflux";
|
|
||||||
DynamicUser = true;
|
|
||||||
LoadCredential = [ "oauth2_secret:${cfg.oauth2SecretFile}" ];
|
|
||||||
RuntimeDirectory = "miniflux";
|
|
||||||
RuntimeDirectoryMode = "0750";
|
|
||||||
WatchdogSec = 60;
|
|
||||||
WatchdogSignal = "SIGKILL";
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = 5;
|
|
||||||
|
|
||||||
# Hardening
|
|
||||||
CapabilityBoundingSet = [ "" ];
|
|
||||||
DeviceAllow = [ "" ];
|
|
||||||
LockPersonality = true;
|
|
||||||
MemoryDenyWriteExecute = true;
|
|
||||||
PrivateDevices = true;
|
|
||||||
PrivateUsers = true;
|
|
||||||
ProcSubset = "pid";
|
|
||||||
ProtectClock = true;
|
|
||||||
ProtectControlGroups = true;
|
|
||||||
ProtectHome = true;
|
|
||||||
ProtectHostname = true;
|
|
||||||
ProtectKernelLogs = true;
|
|
||||||
ProtectKernelModules = true;
|
|
||||||
ProtectKernelTunables = true;
|
|
||||||
ProtectProc = "invisible";
|
|
||||||
RestrictAddressFamilies = [
|
|
||||||
"AF_INET"
|
|
||||||
"AF_INET6"
|
|
||||||
"AF_UNIX"
|
|
||||||
];
|
|
||||||
RestrictNamespaces = true;
|
|
||||||
RestrictRealtime = true;
|
|
||||||
RestrictSUIDSGID = true;
|
|
||||||
SystemCallArchitectures = "native";
|
|
||||||
SystemCallFilter = [
|
|
||||||
"@system-service"
|
|
||||||
"~@privileged"
|
|
||||||
];
|
|
||||||
UMask = "0077";
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = lib.mapAttrs (_: toString) cfg.environment;
|
|
||||||
};
|
|
||||||
environment.systemPackages = [ cfg.package ];
|
|
||||||
|
|
||||||
security.apparmor.policies."bin.miniflux".profile = ''
|
|
||||||
include <tunables/global>
|
|
||||||
${cfg.package}/bin/miniflux {
|
|
||||||
include <abstractions/base>
|
|
||||||
include <abstractions/nameservice>
|
|
||||||
include <abstractions/ssl_certs>
|
|
||||||
include "${pkgs.apparmorRulesFromClosure { name = "miniflux"; } cfg.package}"
|
|
||||||
r ${cfg.package}/bin/miniflux,
|
|
||||||
r @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size,
|
|
||||||
rw /run/miniflux/**,
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
utils,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.custom.sing-box;
|
|
||||||
settingsFormat = pkgs.formats.json { };
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
custom.sing-box = {
|
|
||||||
enable = lib.mkEnableOption "sing-box";
|
|
||||||
|
|
||||||
package = lib.mkPackageOption pkgs "sing-box" { };
|
|
||||||
|
|
||||||
stateDir = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
default = "/var/lib/sing-box";
|
|
||||||
};
|
|
||||||
|
|
||||||
configFile = {
|
|
||||||
urlFile = lib.mkOption { type = lib.types.path; };
|
|
||||||
name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "config.json";
|
|
||||||
};
|
|
||||||
hash = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
example = "9a304bcb87d4c3f1e50f6281f25dd78635255ebde06cd4d2555729ecda43aed4";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
overrideSettings = lib.mkOption {
|
|
||||||
type = lib.types.submodule {
|
|
||||||
freeformType = settingsFormat.type;
|
|
||||||
options = {
|
|
||||||
route = {
|
|
||||||
geoip.path = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
default = "${pkgs.sing-geoip}/share/sing-box/geoip.db";
|
|
||||||
defaultText = lib.literalExpression "\${pkgs.sing-geoip}/share/sing-box/geoip.db";
|
|
||||||
description = lib.mdDoc ''
|
|
||||||
The path to the sing-geoip database.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
geosite.path = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
default = "${pkgs.sing-geosite}/share/sing-box/geosite.db";
|
|
||||||
defaultText = lib.literalExpression "\${pkgs.sing-geosite}/share/sing-box/geosite.db";
|
|
||||||
description = lib.mdDoc ''
|
|
||||||
The path to the sing-geosite database.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
default = { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
networking.firewall.trustedInterfaces = [ "tun0" ];
|
|
||||||
|
|
||||||
systemd.packages = [ cfg.package ];
|
|
||||||
|
|
||||||
systemd.services.sing-box =
|
|
||||||
let
|
|
||||||
configFile = cfg.stateDir + "/${cfg.configFile.name}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
preStart = ''
|
|
||||||
umask 0077
|
|
||||||
mkdir -p /etc/sing-box
|
|
||||||
if ! [ -e ${configFile} ]; then
|
|
||||||
${pkgs.curl}/bin/curl "$(${pkgs.coreutils}/bin/cat ${cfg.configFile.urlFile})" > '${configFile}'
|
|
||||||
test "${cfg.configFile.hash}" $(${pkgs.coreutils}/bin/sha256sum '${configFile}' | ${pkgs.coreutils}/bin/cut -d ' ' -f 1)
|
|
||||||
fi
|
|
||||||
${utils.genJqSecretsReplacementSnippet cfg.overrideSettings "/etc/sing-box/config.json"}
|
|
||||||
${cfg.package}/bin/sing-box merge -c '${configFile}' -c /etc/sing-box/config.json /etc/sing-box/config.json
|
|
||||||
'';
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
6
note.md
6
note.md
|
@ -1,3 +1,9 @@
|
||||||
# nix-tree
|
# nix-tree
|
||||||
|
|
||||||
Demonstrate disk usage by nix-store path.
|
Demonstrate disk usage by nix-store path.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- change caddy admin to unix socket
|
||||||
|
- admin config persist = false
|
||||||
|
- synapse jmalloc
|
||||||
|
- backup all directories under /var/lib/forgejo
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
{
|
{
|
||||||
settings = {
|
settings = {
|
||||||
alertmanagerPort = 9093;
|
alertmanagerPort = 9093;
|
||||||
|
idpUrl = "https://auth.xinyang.life";
|
||||||
|
gotosocialUrl = "https://gts.xiny.li";
|
||||||
|
minifluxUrl = "https://rss.xiny.li";
|
||||||
|
hedgedocDomain = "docs.xiny.li";
|
||||||
|
forgejoDomain = "git.xiny.li";
|
||||||
|
forgejoGitDomain = "git.xiny.li";
|
||||||
|
vaultwardenUrl = "https://vaultwarden.xiny.li";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue