Files
nix-config/modules/nixos/services/nextcloud/default.nix
mjallen18 079493b55e nas
2026-04-08 16:08:00 -05:00

194 lines
6.4 KiB
Nix
Executable File

{
lib,
config,
pkgs,
namespace,
...
}:
let
name = "nextcloud";
cfg = config.${namespace}.services.${name};
net = lib.${namespace}.network;
nextcloudConfig = lib.${namespace}.mkModule {
inherit config name;
serviceName = "nextcloud";
description = "Nextcloud - Secure file sync and sharing platform";
options = { };
moduleConfig = {
# Setup the native NixOS Nextcloud service
services = {
nextcloud = {
enable = true;
package = pkgs.nextcloud33;
hostName = "cloud.mjallen.dev";
home = "${cfg.dataDir}/nextcloud";
datadir = "${cfg.dataDir}/nextcloud";
configureRedis = true;
enableImagemagick = true;
appstoreEnable = true;
# extraApps = with pkgs.${namespace}; {
# richdocumentscode = nextcloud-code-server;
# # richdocuments = nextcloud-richdocuments;
# };
# Use PostgreSQL for database
config = {
dbtype = "pgsql";
dbname = "nextcloud";
dbuser = "nextcloud";
dbhost = "/run/postgresql"; # Socket directory
# dbpassFile = config.sops.secrets."jallen-nas/nextcloud/dbpassword".path;
adminuser = "mjallen";
adminpassFile = config.sops.secrets."matt_password".path;
};
# PHP settings
phpOptions = lib.mkOverride 90 {
memory_limit = "512M";
upload_max_filesize = "10G";
post_max_size = "10G";
output_buffering = "0";
"opcache.interned_strings_buffer" = "16";
"opcache.max_accelerated_files" = "10000";
"opcache.memory_consumption" = "128";
"opcache.save_comments" = "1";
"opcache.revalidate_freq" = "1";
};
# Configure caching for better performance
caching = {
apcu = true;
redis = true;
memcached = false;
};
# Auto-update apps
autoUpdateApps = {
enable = false;
startAt = "05:00:00";
};
# Configure HTTPS if enabled
https = false;
settings = {
installed = true;
auth.bruteforce.protection.enabled = false;
user_oidc = {
auto_provision = false;
};
overwrite.cli.url = "https://cloud.mjallen.dev";
overwriteprotocol = "https";
overwritehost = "cloud.mjallen.dev";
log_type = "file";
default_phone_region = "US";
trusted_proxies = [
net.hosts.nas.lan
"127.0.0.1"
"::1"
];
trusted_domains = [
"cloud.mjallen.dev"
"${net.hosts.nas.lan}:${toString cfg.port}"
];
enabledPreviewProviders = [
"OC\\Preview\\PNG"
"OC\\Preview\\JPEG"
"OC\\Preview\\GIF"
"OC\\Preview\\BMP"
"OC\\Preview\\XBitmap"
"OC\\Preview\\Krita"
"OC\\Preview\\WebP"
"OC\\Preview\\MarkDown"
"OC\\Preview\\TXT"
"OC\\Preview\\OpenDocument"
];
};
};
nginx = {
enable = true;
group = "jallen-nas";
virtualHosts.${config.services.nextcloud.hostName} = {
listen = [
{
inherit (cfg) port;
addr = "0.0.0.0";
ssl = false;
}
];
};
};
};
users = {
users = {
nextcloud = {
isSystemUser = lib.mkForce true;
isNormalUser = lib.mkForce false;
};
};
groups = {
nextcloud = { };
};
};
# Ensure nextcloud services start after PostgreSQL is ready.
# The upstream NixOS module only adds this ordering when services.postgresql.enable
# is true in the same config, but here PostgreSQL is managed separately.
systemd = {
services = {
# Override the empty systemd service created by mkModule.
# The native NixOS nextcloud module doesn't create a persistent "nextcloud.service"
# (it uses PHP-FPM pools and cron instead), so we clear this to avoid the error:
# "Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing."
nextcloud = lib.mkForce { };
nextcloud-setup = {
after = [ "postgresql.service" ];
requires = [ "postgresql.service" ];
serviceConfig =
let
# Extract the override.config.php store-path from the already-evaluated
# tmpfiles rules list at Nix eval time, so we never have to parse files at
# runtime. The upstream module emits exactly one rule of the form:
# "L+ <dest> - - - - <storepath>"
overrideLine = lib.findFirst (
r: lib.hasInfix "override.config.php" r
) null config.systemd.tmpfiles.rules;
overrideStorePath =
if overrideLine != null then lib.last (lib.splitString " " overrideLine) else null;
in
lib.mkIf (overrideStorePath != null) {
# systemd-tmpfiles refuses to create the override.config.php symlink because
# /media/nas/main is owned by nix-apps (not root/nextcloud), triggering an
# "unsafe path transition" error. Work around this by creating the symlink
# directly as root (the '+' prefix) before the setup script's ownership check.
# The target store path is resolved at Nix eval time so it is always current.
ExecStartPre = [
(
"+"
+ pkgs.writeShellScript "nextcloud-fix-override-config" ''
dest="${cfg.dataDir}/nextcloud/config/override.config.php"
echo "Creating symlink: $dest -> ${overrideStorePath}"
${pkgs.coreutils}/bin/ln -sf "${overrideStorePath}" "$dest"
''
)
];
};
};
nextcloud-update-db = {
after = [ "postgresql.service" ];
requires = [ "postgresql.service" ];
};
};
};
};
};
in
{
imports = [ nextcloudConfig ];
}