Compare commits

..

No commits in common. "f2501365c43ecdfe8bb90745e7d1255d797ebe7f" and "358f2296ce00c8f39a8b955dba19a71596d03d79" have entirely different histories.

8 changed files with 86 additions and 302 deletions

View file

@ -109,8 +109,6 @@ in
matrix-authentication-service # mas-cli for migration matrix-authentication-service # mas-cli for migration
]; ];
security.sudo.enable = true;
networking.hostName = hostname; networking.hostName = hostname;
services.openssh = { services.openssh = {

View file

@ -571,36 +571,6 @@ in {
''; '';
}; };
# Provision an OpenClaw bot user in MAS and issue a long-lived compatibility
# access token. Runs once; the token is persisted in /var/lib/mas/.
systemd.services.matrix-bot-provision = {
description = "Provision Matrix bot user for OpenClaw";
after = [ "matrix-authentication-service.service" ];
before = [ "podman-openclaw.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
path = [ "/run/wrappers" ];
script = ''
TOKEN_FILE="/persist/openclaw-token"
if [ ! -f "$TOKEN_FILE" ]; then
sudo -u mas ${masPackage}/bin/mas-cli manage register-user \
--config /run/mas/config.yaml \
--username openclaw \
--display-name "OpenClaw Bot" \
--yes 2>/dev/null || true
TOKEN=$(sudo -u mas ${masPackage}/bin/mas-cli manage issue-compatibility-token \
--config /run/mas/config.yaml \
openclaw OPENCLAW 2>&1 \
| ${pkgs.gnugrep}/bin/grep -oP 'token issued: \K\S+')
echo "$TOKEN" > "$TOKEN_FILE"
chmod 0444 "$TOKEN_FILE"
fi
'';
};
# Mattermost bridge (bridgev2 — attrs replace entirely, so include all needed fields) # Mattermost bridge (bridgev2 — attrs replace entirely, so include all needed fields)
services.mautrix-mattermost = { services.mautrix-mattermost = {
enable = true; enable = true;

View file

@ -66,7 +66,6 @@ in
environment.persistence."/nix/persist/system" = { environment.persistence."/nix/persist/system" = {
hideMounts = true; hideMounts = true;
directories = [ directories = [
"/var/lib/downloads"
"/var/lib/pyload" "/var/lib/pyload"
"/var/lib/jellyfin" "/var/lib/jellyfin"
"/var/lib/audiobookshelf" "/var/lib/audiobookshelf"

View file

@ -39,7 +39,7 @@ let
# to a non-local peer means a download is in flight. # to a non-local peer means a download is in flight.
pyload_conns=$(${pkgs.iproute2}/bin/ss -H -t -n -p \ pyload_conns=$(${pkgs.iproute2}/bin/ss -H -t -n -p \
state established state syn-sent state syn-recv 2>/dev/null \ state established state syn-sent state syn-recv 2>/dev/null \
| grep -F 'pyload' \ | grep -F '"pyload"' \
| awk '{print $5}' \ | awk '{print $5}' \
| grep -Ev '${localPeerRegex}' || true) | grep -Ev '${localPeerRegex}' || true)
if [[ -n "$pyload_conns" ]]; then if [[ -n "$pyload_conns" ]]; then

View file

@ -11,7 +11,6 @@
./modules/bitwarden ./modules/bitwarden
./modules/authelia.nix ./modules/authelia.nix
./modules/collabora.nix ./modules/collabora.nix
./modules/ocis.nix
./modules/nextcloud ./modules/nextcloud
./modules/rustdesk.nix ./modules/rustdesk.nix
./modules/postgresql.nix ./modules/postgresql.nix
@ -55,11 +54,6 @@
"openssl-1.1.1w" "openssl-1.1.1w"
]; ];
# oCIS (ownCloud Infinite Scale) has an unfree license
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"ocis_5-bin"
];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
vim vim
davfs2 davfs2

View file

@ -58,6 +58,7 @@ in {
}; };
settings = { settings = {
theme = "dark"; theme = "dark";
default_redirection_url = "https://cloonar.com";
# log = { # log = {
# level = "debug"; # level = "debug";
@ -116,24 +117,27 @@ in {
}; };
session = { session = {
name = "authelia_session";
expiration = "12h";
inactivity = "45m";
remember_me_duration = "1M";
domain = "cloonar.com";
redis = { redis = {
host = "/run/redis-authelia/redis.sock"; host = "/run/redis-authelia/redis.sock";
}; };
# Authelia 4.38+ replaced top-level session.domain with per-cookie # todo: enable with 4.38
# entries. Each entry needs an authelia_url, so only cloonar.com is # cookies = [
# configured here — adding cloonar.dev / gbv-aktuell.at would require # {
# separate Authelia endpoints on those domains. # domain = "cloonar.com";
cookies = [ # }
{ # {
name = "authelia_session"; # domain = "cloonar.dev";
domain = "cloonar.com"; # }
authelia_url = "https://auth.cloonar.com"; # {
default_redirection_url = "https://cloonar.com"; # domain = "gbv-aktuell.at";
expiration = "12h"; # same_site = "strict";
inactivity = "45m"; # }
remember_me = "1M"; # ];
}
];
}; };
regulation = { regulation = {
@ -169,23 +173,6 @@ in {
oidc = { oidc = {
## The other portions of the mandatory OpenID Connect 1.0 configuration go here. ## The other portions of the mandatory OpenID Connect 1.0 configuration go here.
## See: https://www.authelia.com/c/oidc ## See: https://www.authelia.com/c/oidc
lifespans = {
custom = {
ocis = {
access_token = "2 days";
refresh_token = "3 days";
};
};
};
cors = {
endpoints = [
"authorization"
"token"
"revocation"
"introspection"
"userinfo"
];
};
authorization_policies = { authorization_policies = {
"admin-only" = { "admin-only" = {
default_policy = "deny"; default_policy = "deny";
@ -297,79 +284,6 @@ in {
]; ];
userinfo_signing_algorithm = "none"; userinfo_signing_algorithm = "none";
} }
# oCIS (ownCloud Infinite Scale) - web client (public, PKCE)
{
id = "ocis";
description = "ownCloud Infinite Scale";
lifespan = "ocis";
public = true;
authorization_policy = "internal";
require_pkce = true;
pkce_challenge_method = "S256";
redirect_uris = [
"https://files.cloonar.com/"
"https://files.cloonar.com/oidc-callback.html"
"https://files.cloonar.com/oidc-silent-redirect.html"
"https://files.cloonar.com/apps/openidconnect/redirect"
];
scopes = [ "openid" "offline_access" "groups" "profile" "email" ];
response_types = [ "code" ];
grant_types = [ "authorization_code" "refresh_token" ];
access_token_signed_response_alg = "none";
userinfo_signing_algorithm = "none";
token_endpoint_auth_method = "none";
}
# oCIS Desktop - static credentials hardcoded in the oCIS desktop app
{
id = "xdXOt13JKxym1B1QcEncf2XDkLAexMBFwiT9j6EfhhHFJhs2KM9jbjTmf8JBXE69";
description = "ownCloud Infinite Scale (Desktop)";
secret = "$pbkdf2-sha512$310000$NR4tztBecptj1ZiITK/Ktw$GkFNBfq1B3T1lDTKMci1aO8iulQFNlEtfydLwTrNTKIfrQFjM7EiOBaHGOBC7ohPaNfYCRAYYzcP2fDQf5XRGQ";
public = false;
authorization_policy = "internal";
require_pkce = true;
pkce_challenge_method = "S256";
redirect_uris = [ "http://127.0.0.1" "http://localhost" ];
scopes = [ "openid" "offline_access" "groups" "profile" "email" ];
response_types = [ "code" ];
grant_types = [ "authorization_code" "refresh_token" ];
access_token_signed_response_alg = "none";
userinfo_signing_algorithm = "none";
token_endpoint_auth_method = "client_secret_basic";
}
# oCIS Android - static credentials hardcoded in the oCIS Android app
{
id = "e4rAsNUSIUs0lF4nbv9FmCeUkTlV9GdgTLDH1b5uie7syb90SzEVrbN7HIpmWJeD";
description = "ownCloud Infinite Scale (Android)";
secret = "$pbkdf2-sha512$310000$NjEumkph77Gql.CH0Oq3zg$I9ubOZ3VRCXPbHpW1U4bQmvLgP5DdiFeGgple2nIjtUJsFgkdiV/hcCt1h6adr1uvJSJAtHDRnMhYf3Zp2BpcQ";
public = false;
authorization_policy = "internal";
require_pkce = true;
pkce_challenge_method = "S256";
redirect_uris = [ "oc://android.owncloud.com" ];
scopes = [ "openid" "offline_access" "groups" "profile" "email" ];
response_types = [ "code" ];
grant_types = [ "authorization_code" "refresh_token" ];
access_token_signed_response_alg = "none";
userinfo_signing_algorithm = "none";
token_endpoint_auth_method = "client_secret_basic";
}
# oCIS iOS - static credentials hardcoded in the oCIS iOS app
{
id = "mxd5OQDk6es5LzOzRvidJNfXLUZS2oN3oUFeXPP8LpPrhx3UroJFduGEYIBOxkY1";
description = "ownCloud Infinite Scale (iOS)";
secret = "$pbkdf2-sha512$310000$.nIk0IUua7n8VAUoR85yyA$6UhT/gi7spH/0PRqTa6clz7QMRSmP/FZ0BDIumJupM4V2Ai6MgGKdzlEaNTc2IDqpGL3NxF626g4zAHFRgD7Zg";
public = false;
authorization_policy = "internal";
require_pkce = true;
pkce_challenge_method = "S256";
redirect_uris = [ "oc://ios.owncloud.com" "oc.ios://ios.owncloud.com" ];
scopes = [ "openid" "offline_access" "groups" "profile" "email" ];
response_types = [ "code" ];
grant_types = [ "authorization_code" "refresh_token" ];
access_token_signed_response_alg = "none";
userinfo_signing_algorithm = "none";
token_endpoint_auth_method = "client_secret_basic";
}
]; ];
}; };
}; };
@ -409,13 +323,16 @@ in {
proxy_connect_timeout 360; proxy_connect_timeout 360;
# Basic Proxy Config # Basic Proxy Config
# Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host proxy_set_header Host $host;
# and Connection are already set by recommendedProxySettings; redefining
# them here caused duplicate headers and fasthttp "too many Host headers" 400s.
proxy_set_header X-Original-URL $scheme://$http_host$request_uri; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
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 $http_host;
proxy_set_header X-Forwarded-Uri $request_uri; proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on; proxy_set_header X-Forwarded-Ssl on;
proxy_redirect http:// $scheme://; proxy_redirect http:// $scheme://;
proxy_set_header Connection "";
proxy_cache_bypass $cookie_session; proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session; proxy_no_cache $cookie_session;
proxy_buffers 64 256k; proxy_buffers 64 256k;

View file

@ -1,93 +0,0 @@
{ config, lib, pkgs, ... }:
{
sops.secrets.ocis-admin-password = {
owner = "ocis";
};
# Upstream services.ocis module adds ReadOnlyPaths = [ configDir ] to the
# systemd unit, which makes systemd fail the namespace setup if the path
# does not exist, and it never runs `ocis init` to populate ocis.yaml with
# the service's internal secrets. Run init in a separate oneshot so the
# sandbox restrictions of ocis.service don't block writes to configDir.
systemd.services.ocis-init = {
description = "Initialize oCIS config (one-shot)";
before = [ "ocis.service" ];
requiredBy = [ "ocis.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "ocis";
Group = "ocis";
StateDirectory = "ocis";
LoadCredential = "admin-password:${config.sops.secrets.ocis-admin-password.path}";
};
script = ''
install -d -m 0700 /var/lib/ocis/config
if [ ! -f /var/lib/ocis/config/ocis.yaml ]; then
${lib.getExe pkgs.ocis_5-bin} init \
--config-path /var/lib/ocis/config \
--admin-password "$(cat "$CREDENTIALS_DIRECTORY/admin-password")" \
--insecure true
fi
'';
};
services.ocis = {
enable = true;
url = "https://files.cloonar.com";
address = "127.0.0.1";
port = 9200;
stateDir = "/var/lib/ocis";
configDir = "/var/lib/ocis/config";
environment = {
# Proxy - SSL terminated at nginx
PROXY_TLS = "false";
OCIS_INSECURE = "false";
# OIDC - Authelia
PROXY_OIDC_ISSUER = "https://auth.cloonar.com";
PROXY_OIDC_REWRITE_WELLKNOWN = "true";
PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD = "none";
PROXY_OIDC_SKIP_USER_INFO = "false";
WEB_OIDC_CLIENT_ID = "ocis";
# Auto-provision user accounts from OIDC claims
PROXY_AUTOPROVISION_ACCOUNTS = "true";
PROXY_AUTOPROVISION_CLAIM_USERNAME = "preferred_username";
PROXY_AUTOPROVISION_CLAIM_EMAIL = "email";
PROXY_AUTOPROVISION_CLAIM_DISPLAYNAME = "name";
PROXY_AUTOPROVISION_CLAIM_GROUPS = "groups";
# Disable demo users
IDM_CREATE_DEMO_USERS = "false";
# Move internal services off their defaults where Prometheus exporters
# already bind on this host:
# - node-exporter owns 9100 (oCIS web default)
# - blackbox-exporter owns 9115 (oCIS webdav default)
WEB_HTTP_ADDR = "127.0.0.1:19100";
WEBDAV_HTTP_ADDR = "127.0.0.1:19115";
};
};
# Nginx reverse proxy
services.nginx.virtualHosts."files.cloonar.com" = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
locations."/" = {
proxyPass = "http://127.0.0.1:9200";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size 10G;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
'';
};
};
}

File diff suppressed because one or more lines are too long