249 lines
9.1 KiB
Nix
Executable File
249 lines
9.1 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;
|
|
|
|
# Bootstrap config.php written when the file is absent/empty.
|
|
# Satisfies Nextcloud's Config.php writeData() guard (needs 'version')
|
|
# and the setup script's `-s` check (needs non-empty file).
|
|
# passwordsalt/secret/instanceid are intentionally left empty here —
|
|
# they must be populated manually or via SOPS before first use.
|
|
bootstrapConfig = pkgs.writeText "nextcloud-bootstrap-config.php" (
|
|
"<?php\n"
|
|
+ "$"
|
|
+ "CONFIG = [\n"
|
|
+ " 'installed' => true,\n"
|
|
+ " 'version' => '${config.services.nextcloud.package.version}',\n"
|
|
+ " 'datadirectory' => '${cfg.dataDir}/nextcloud/data',\n"
|
|
+ " 'dbtype' => 'pgsql',\n"
|
|
+ " 'dbname' => 'nextcloud',\n"
|
|
+ " 'dbhost' => '/run/postgresql',\n"
|
|
+ " 'dbuser' => 'nextcloud',\n"
|
|
+ " 'dbpassword' => "
|
|
+ "''"
|
|
+ ",\n"
|
|
+ " 'instanceid' => "
|
|
+ "''"
|
|
+ ",\n"
|
|
+ " 'passwordsalt' => "
|
|
+ "''"
|
|
+ ",\n"
|
|
+ " 'secret' => "
|
|
+ "''"
|
|
+ ",\n"
|
|
+ "];\n"
|
|
);
|
|
in
|
|
lib.mkIf (overrideStorePath != null) {
|
|
# systemd-tmpfiles refuses to create paths under /media/nas/main because
|
|
# of an "unsafe path transition" (owned by nix-apps, not root/nextcloud).
|
|
# Work around by creating the required dirs/symlinks as root ('+' prefix)
|
|
# before the setup script's ownership check runs.
|
|
ExecStartPre = [
|
|
(
|
|
"+"
|
|
+ pkgs.writeShellScript "nextcloud-fix-override-config" ''
|
|
ncdir="${cfg.dataDir}/nextcloud"
|
|
|
|
# Ensure required directories exist with correct ownership
|
|
for dir in "$ncdir" "$ncdir/config" "$ncdir/data" "$ncdir/store-apps"; do
|
|
if [ ! -d "$dir" ]; then
|
|
${pkgs.coreutils}/bin/mkdir -p "$dir"
|
|
fi
|
|
${pkgs.coreutils}/bin/chown nextcloud:nextcloud "$dir"
|
|
${pkgs.coreutils}/bin/chmod 0750 "$dir"
|
|
done
|
|
|
|
# override.config.php symlink (updated each generation)
|
|
dest="$ncdir/config/override.config.php"
|
|
echo "Creating symlink: $dest -> ${overrideStorePath}"
|
|
${pkgs.coreutils}/bin/ln -sf "${overrideStorePath}" "$dest"
|
|
|
|
# If config.php is absent or empty, copy in a bootstrap stub.
|
|
# Nextcloud's Config.php writeData() guard requires 'version' in the
|
|
# merged cache, and the setup script's -s check requires a non-empty
|
|
# file. The real runtime settings come from override.config.php via
|
|
# array_replace_recursive; this stub just satisfies those two guards.
|
|
cfgfile="$ncdir/config/config.php"
|
|
if [ ! -s "$cfgfile" ]; then
|
|
echo "Writing bootstrap config.php"
|
|
${pkgs.coreutils}/bin/cp ${bootstrapConfig} "$cfgfile"
|
|
${pkgs.coreutils}/bin/chown nextcloud:nextcloud "$cfgfile"
|
|
${pkgs.coreutils}/bin/chmod 0640 "$cfgfile"
|
|
fi
|
|
''
|
|
)
|
|
];
|
|
};
|
|
};
|
|
nextcloud-update-db = {
|
|
after = [ "postgresql.service" ];
|
|
requires = [ "postgresql.service" ];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
in
|
|
{
|
|
imports = [ nextcloudConfig ];
|
|
}
|