CCE

Nextcloud on Wobserver

Contents

Nextcloud is a self hosted personal information server. Think of it like Google Workspace or Office365 but self-hosted and lower-quality. I use it to share files with friends over WebDAV and NC's easy link-sharing feature, I use it to sync my calendar and contacts with my phone and in to org-mode with org-caldav.

Here is how it's deployed to The Wobserver:

nix:tangle ~/nix/nixos/nextcloud.nix
{ config, pkgs, lib, ... }:

let
  domains = [
    "files.fontkeming.fail"
    "nc.rix.si"
  ];
  edgeIPs = [ "100.89.170.115" "100.112.80.23" ];
in
{
  sops.secrets.nextcloud_admin_pass.owner = "nextcloud";

  services.postgresql.ensureDatabases = ["nextcloud"];
  services.postgresql.ensureUsers = [
    {
      name = "nextcloud";
      ensureDBOwnership = true;
    }
  ];

  services.prometheus.exporters.nextcloud = {
    enable = false;
    passwordFile = config.sops.secrets.nextcloud_admin_pass.path;
    username = "admin";
    url = "https://files.fontkeming.fail";
  };

  users.groups.tank = {
    members = [ "rrix" "nextcloud" ];
    gid = 10001;
  };

  # services.redis.servers.nextcloud = {
  #   enable = true;
  #   port = 6380;
  # };

  services.nextcloud = {
    package = pkgs.nextcloud32;
    enable = true;
    home = "/srv/nextcloud";
    appstoreEnable = true;
    hostName = lib.head domains;
    https = true;
    webfinger = true;

    caching.redis = true;

    # to talk to other local wobserver services

    phpOptions."opcache.interned_strings_buffer" = "23";
    config = {
      dbhost = "/run/postgresql";
      dbtype = "pgsql";
      adminpassFile = config.sops.secrets.nextcloud_admin_pass.path;
      adminuser = "admin";
    };
    settings = {
      allow_local_remote_servers = true;
      trusted_proxies = edgeIPs;
      trusted_domains = domains;
      syslog_tag = "nextcloud";
      # log_type = "systemd";
      log_type = "file";
      logfile = "/var/log/nextcloud/nextcloud.log";
      loglevel = 3;
      preview_ffmpeg_path = "${pkgs.ffmpeg-headless}/bin/ffmpeg";
      "memories.exiftool" = "${lib.getExe pkgs.exiftool}";
      "memories.vod.ffmpeg" = "${lib.getExe pkgs.ffmpeg-headless}";
      "memories.vod.ffprobe" = "${pkgs.ffmpeg-headless}/bin/ffprobe";

      # redis = {
      #   host="localhost";
      #   port=6380;
      #   timeout=0.0;
      #   read_timeout=0.0;
      # };
    };

    # phpExtraExtensions = phpPkgs: with phpPkgs; [
    #   systemd
    # ];
  };

  systemd.tmpfiles.settings."50-nextcloud" = {
    "/var/log/nextcloud" = {
      d = {
        group = "nextcloud";
        mode = "0775";
        user = "nextcloud";
      };
    };
  };

  environment.systemPackages = [ config.services.nextcloud.package pkgs.nodejs ];
  systemd.services.phpfpm-nextcloud.path = [ pkgs.perl ];
  systemd.services.nextcloud-cron.path = [ pkgs.perl ];
  systemd.services.nextcloud-setup.after = [ "postgresql.service" ];

  services.nginx.virtualHosts."${lib.head domains}" = {
    serverAliases = lib.tail domains;
    useACMEHost = "fontkeming.fail";
    addSSL = true;
    
    extraConfig = ''
      add_header Referrer-Policy "no-referrer" always;
      add_header X-Content-Type-Options "nosniff" always;
      add_header X-Download-Options "noopen" always;
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header X-Permitted-Cross-Domain-Policies "none" always;
      add_header X-Robots-Tag "none" always;
      add_header X-XSS-Protection "1; mode=block" always;
      fastcgi_hide_header X-Powered-By;
    '';
  };
}

NEXT validate this

NEXT grafana dashboards for nextcloud stats

NEXT recommended apps and configuration tweaks, how to best use nextcloud on the wobserver