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:
xinyangli 2024-12-04 16:02:03 +08:00
parent 947e97ce4e
commit ad9c205fc5
Signed by: xin
SSH key fingerprint: SHA256:UU5pRTl7NiLFJbWJZa+snLylZSXIz5rgHmwjzv8v4oE
18 changed files with 263 additions and 670 deletions

View file

@ -10,6 +10,10 @@
./services/gotosocial.nix
./services/synapse.nix
./services/restic.nix
./services/miniflux.nix
./services/hedgedoc.nix
./services/forgejo.nix
./services/vaultwarden.nix
];
networking.hostName = "biotite";

View file

@ -5,6 +5,12 @@ synapse:
restic:
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]
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:
kms: []
gcp_kms: []
@ -29,8 +35,8 @@ sops:
RzBMVDNjS29SUkdRK3dIV01sU0hYR3cK1SbvKAM6Gpsffv3HIi/WtWnCZUBic0AT
ZRv4pvJBx1oxWsKIHW0t6VrqWMQ+suup8p6dW+h5HE8Z4ciIMrXLEg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-12-03T07:38:24Z"
mac: ENC[AES256_GCM,data:KMKdwgu9+3DjG1lrQYQEz/jYWsHUBK6RgHRyRKzWG0jTDg30owRpCgnSnX5gHzygmSYSnVRtcTOWzqm5bI7/KJkXBivaqkLqCh6EHnTj+pnAHmeEOAjoOVLOMSCEYvHMf/EuJIL199Hf2G12LtulDJV7Wi5r5Jy8L9odVlYuM9g=,iv:WTeqWdIztScZnXc2hzI7JHO/4ySgqycOp2eN9EPTQpw=,tag:lTMrE5JVVFCIDehXCxJZoQ==,type:str]
lastmodified: "2024-12-04T05:07:32Z"
mac: ENC[AES256_GCM,data:hD7645epMVYHU6K1AZsHu+fp/PMIqqiZpv7K4Vxzo84slzn0CfZSYaVaYxKNGjOIgEGN9D2FFmq9WL6ChMskMfqqafY7qDpSQqFp9TUwb5jN34XcQg9vplfNw+lMqsnDCt1HENWErRnlDxTI2ctSEcx3UKGBOQ3ttLzUIySdnFY=,iv:reOsqvc8E3l8yxb5gVcqF/rU2o2yKmaUyGNRNT+Skx8=,tag:eBoV8G+X0cPs3Q1xAuv55w==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.1

View 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";
}

View 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" ];
}

View 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}
'';
}

View 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}
'';
};
}

View file

@ -21,12 +21,6 @@
gts_env = {
owner = "gotosocial";
};
hedgedoc_env = {
owner = "hedgedoc";
};
grafana_oauth_secret = {
owner = "grafana";
};
"miniflux/oauth2_secret" = {
owner = "root";
};

View file

@ -1,4 +1,12 @@
{ config, lib, ... }:
{ my-lib, ... }:
let
inherit (my-lib.settings)
gotosocialUrl
minifluxUrl
hedgedocDomain
forgejoDomain
;
in
{
services.kanidm.provision = {
enable = true;
@ -76,8 +84,8 @@
systems.oauth2 = {
forgejo = {
displayName = "ForgeJo";
originUrl = "https://git.xinyang.life/user/oauth2/kanidm/callback";
originLanding = "https://git.xinyang.life/user/oauth2/kanidm";
originUrl = "https://${forgejoDomain}/user/oauth2/kanidm/callback";
originLanding = "https://${forgejoDomain}/user/oauth2/kanidm";
allowInsecureClientDisablePkce = true;
scopeMaps = {
forgejo-access = [
@ -113,8 +121,8 @@
};
gotosocial = {
displayName = "GoToSocial";
originUrl = "https://gts.xiny.li/auth/callback";
originLanding = "https://gts.xiny.li/auth/callback";
originUrl = "${gotosocialUrl}/auth/callback";
originLanding = "${gotosocialUrl}/auth/callback";
allowInsecureClientDisablePkce = true;
scopeMaps = {
gts-users = [
@ -150,8 +158,8 @@
hedgedoc = {
displayName = "HedgeDoc";
originUrl = "https://docs.xinyang.life/auth/oauth2/callback";
originLanding = "https://docs.xinyang.life/auth/oauth2";
originUrl = "https://${hedgedocDomain}/auth/oauth2/callback";
originLanding = "https://${hedgedocDomain}/auth/oauth2";
allowInsecureClientDisablePkce = true;
scopeMaps = {
hedgedoc-users = [
@ -180,9 +188,8 @@
};
miniflux = {
displayName = "Miniflux";
originUrl = "https://rss.xinyang.life/oauth2/oidc/callback";
originLanding = "https://rss.xinyang.life/oauth2/oidc/redirect";
originUrl = "${minifluxUrl}/oauth2/oidc/callback";
originLanding = "${minifluxUrl}/oauth2/oidc/redirect";
scopeMaps = {
miniflux-users = [
"openid"

View file

@ -23,26 +23,6 @@ in
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 = {
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 = {
isSystemUser = true;
group = "conduit";
@ -150,111 +96,6 @@ in
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 = {
enable = true;
virtualHosts."xinyang.life:443".extraConfig = ''
@ -265,12 +106,6 @@ in
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 = ''
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 = ''
reverse_proxy unix/${config.services.ntfy-sh.settings.listen-unix}
@httpget {
@ -298,13 +129,5 @@ in
}
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}
'';
};
}

View file

@ -73,16 +73,16 @@ with my-lib;
{
inherit passwordFile;
name = "gotosocial";
address = "xinyang.life";
address = "gts.xiny.li";
}
{
inherit passwordFile;
name = "miniflux";
address = "rss.xinyang.life";
address = "rss.xiny.li";
}
{
name = "ntfy";
address = "ntfy.xinyang.life";
address = "ntfy.xiny.li";
}
{
name = "grafana-eu";