用 NixOS 在本地搭建 Nextcloud

在之前的文章中，我们已经安装了适用于服务器的 NixOS。本文将在此基础上搭建 Nextcloud。

博主在搭建 Nextcloud 时遇到了很大困难，主要原因是无法发送邮件、NixOS 官方文档简陋。所以我甚至写了一个更好的 Nextcloud NixOS Wiki。在折腾完 Nextcloud+NixOS 之后，试一试提交上去换掉现在的 Wiki。

实际上你不需要按照博客的做法一步一步来，你完全可以直接下载我配置好的configuration.nix，然后按照自己的需求做修改。

为什么是 Nextcloud

Nextcloud 是一个开源的云存储服务，可以用于搭建私有云。它的功能非常强大，可以用于文件存储、日历、笔记、聊天等等。虽然 Nextcloud 使用了过时的 PHP, 但是因为它的功能实在是强大，找不到比较好的替代品，所以还是选择了 Nextcloud。

除了Nextcloud之外，博主还尝试了这些开源云存储服务：

pydio：功能同样强大，但是没有 Nix 包，NixOS 安装起来比较麻烦。

Seafile：足够强大的替代品，有 Nix 包，但是缺少文档，部署比较麻烦。

ownCloud：Nextcloud 的前身，功能不够强大，而且更新不稳定。

cloudreve：功能不够强大，只能存储文件，而且没有 Nix 包。

本地搭建 Nextcloud 的基本流程

安装 Nextcloud 包

安装 Nextcloud 非常简单，只需要修改/etc/nixos/configuration.nix文件，在environment.systemPackages中添加nextcloud即可。

Copy
environment.systemPackages = with pkgs; [
nextcloud26
];

注意：Nextcloud 的 Nix 包是nextcloud+ 版本号，而不是nextcloud。

先不要着急运行nixos-rebuild switch，现在还没有配置 Nextcloud.

初次配置

NixOS 手册中给出了这样的配置：

Copy
{
services.nextcloud = {
enable = true;
hostName = "nextcloud.tld";
config = {
dbtype = "pgsql";
dbuser = "nextcloud";
dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself
dbname = "nextcloud";
adminpassFile = "/path/to/admin-pass-file";
adminuser = "root";
};
};

services.postgresql = {
enable = true;
ensureDatabases = [ "nextcloud" ];
ensureUsers = [
{ name = "nextcloud";
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
}
];
};

# ensure that postgres is running *before* running the setup
systemd.services."nextcloud-setup" = {
requires = ["postgresql.service"];
after = ["postgresql.service"];
};di vi

networking.firewall.allowedTCPPorts = [ 80 443 ];
}

这段配置的含义是：

启用 Nextcloud 服务

指定域名为nextcloud.tld

指定数据库为 PostgreSQL，并给出了数据库的具体配置

指定了服务的启动顺序

开放了 80 和 443 端口

指定存放 Nextcloud 管理员的密码文件为/path/to/admin-pass-file

/path/to/admin-pass-file不是一个实际的路径，而是一个占位符，需要我们自己指定。按照 NixOS 的要求，这个文件必须可以被nextcloud用户访问。但经过博主测试，发现这个文件所在的目录也需要能够被nextcloud用户访问。因此，我们需要将这个文件放在/nextcloud目录下，然后将/nextcloud目录的权限设置为777。

将/path/to/admin-pass-file改为/nextcloud/nextcloud-admin-pass，然后

Copy
# 以root用户运行
cd /
mkdir nextcloud
chown nextcloud nextcloud/
chmod 777 nextcloud/
cd nextcloud
vim nextcloud-admin-pass
# 写入密码
nixos-rebuild switch

由于是本地测试环境，暂时将nextcloud.tld修改为nextcloud.nixos（因为博主的局域网有自建的 dns 服务器，如果你没有，建议改成地址）。

在完成构建之后，访问http://nextcloud.nixos/，就可以看到类似下图的 Nextcloud 的安装界面了。

不同版本的 Nextcloud 的安装界面可能不同，但是大同小异。

输入service.nextcloud.config.adminuser中指定的用户名和/nextcloud/nextcloud-admin-pass中指定的密码，就可以完成安装了。

在 nix 配置文件中安装 Nextcloud 的应用（简易用法）

上述配置部署的 nextcloud 只安装了寥寥几个应用，但 Nextcloud 是一个强大的平台，可以通过安装应用极大地拓宽功能。在 Nextcloud 的应用商店中，可以找到并安装很多应用，但是在 NixOS 中，使用 Nix 包管理器安装应用是一个更好的选择。

NixWiki中提供了安装应用的示例，例如

Copy
services.nextcloud = {
enable = true;
[...]
package = pkgs.nextcloud26;
extraApps = with pkgs.nextcloud26Packages.apps; {
inherit mail news contacts;
};
extraAppsEnable = true;
};

这段配置安装了 mail、news 和 contacts 三个应用。但是这些应用的名称在 Nextcloud 的应用商店中是找不到的，不过我们可以在 NixWiki 的Some apps中找到这些应用的名称。

本文发布时，这些应用的名称如下：

Copy
[
"bookmarks",
"calendar",
"contacts",
"deck",
"keeweb",
"mail",
"news",
"notes",
"onlyoffice",
"polls",
"tasks",
"twofactor_webauthn"
]

显然这些应用是不够用的，不过，还有其他的方法安装应用。

在 nix 配置文件中安装 Nextcloud 应用商店中的应用

NixWiki 还给出了在 nix 配置文件中，通过 Nextcloud 应用商店安装应用的方法，例如

Copy
services.nextcloud = {
enable = true;
[...]
extraApps = {
mail = pkgs.fetchNextcloudApp rec {
url = "https://github.com/nextcloud-releases/mail/releases/download/v1.14.1/mail-v1.14.1.tar.gz";
sha256 = "sha256-sQUsYC3cco6fj9pF2l1NrCEhA3KJoOvJRhXvBlVpNqo=";
};
contacts = pkgs.fetchNextcloudApp rec {
url = "https://github.com/nextcloud-releases/contacts/releases/download/v4.2.2/contacts-v4.2.2.tar.gz";
sha256 = "sha256-eTc51pkg3OdHJB7X4/hD39Ce+9vKzw1nlJ7BhPOzdy0=";
};
};
extraAppsEnable = true;
};

这段配置安装了 mail 和 contacts 两个应用。我们可以在Nexcloud 应用商店中找到应用的下载链接，然后将其添加到配置文件中。

注意：通过这种方法安装的应用需要手动更新。在版本更新时，你需要再次手动填写新的下载链接。（当然，也可以使用 Nextcloud 内的应用商店更新）

博主安装了这些应用

Copy
services.nextcloud = {
enable = true;
package = pkgs.nextcloud26;
[...]

extraApps = {
contacts = pkgs.nextcloud26Packages.apps.contacts;
mail = pkgs.nextcloud26Packages.apps.mail;
calendar = pkgs.fetchNextcloudApp rec {
url = "https://github.com/nextcloud-releases/calendar/releases/download/v4.3.4/calendar-v4.3.4.tar.gz";
sha256 = "0pj1h86kdnckzfrn13hllgps4wa921z4s24pg5d2666fqx89rwrv";
};
notes = pkgs.fetchNextcloudApp rec {
url = "https://github.com/nextcloud-releases/notes/releases/download/v4.7.2/notes.tar.gz";
sha256 = "0klqf8dixrrb8yp8cc60ggnvhmqb3yh9f6y1281jn8ia5jml622v";
};
camerarawpreviews = pkgs.fetchNextcloudApp rec {
url = "https://github.com/ariselseng/camerarawpreviews/releases/download/v0.8.1/camerarawpreviews_nextcloud.tar.gz";
sha256 = "1n1395m81m81klxzxd03ww07m0xjp0blbmx23y457k62j3kkr0m2";
};
drawio = pkgs.fetchNextcloudApp rec {
url = "https://github.com/jgraph/drawio-nextcloud/releases/download/v2.1.1/drawio-v2.1.1.tar.gz";
sha256 = "0frizrgkbmc3mhhap7cq45z43l4whzkszx7v0v0q2ylmq8sbxszm";
};
registration = pkgs.fetchNextcloudApp rec {
url = "https://github.com/nextcloud-releases/registration/releases/download/v2.1.0/registration-v2.1.0.tar.gz";
sha256 = "07dqc670qmdb3c8jjnj7azxxspjhiv6m9nrj960y3rjabyzy25m9";
};
music = pkgs.fetchNextcloudApp rec {
url = "https://github.com/owncloud/music/releases/download/v1.8.3/music_1.8.3_for_nextcloud.tar.gz";
sha256 = "1kajm5ppp63g42xdvkmv0glw7snsc2fi7pcra1sg4kd005ffz42d";
};
bookmarks = pkgs.fetchNextcloudApp rec {
url = "https://github.com/nextcloud/bookmarks/releases/download/v13.0.1/bookmarks-13.0.1.tar.gz";
sha256 = "0xx331bgly91y8ncxk36ha3ncrr2xlivblfi7rix6ffkrdx73yb9";
};
};

}

你可以使用nix-prefetch-url --unpack <url>命令获取 tar.gz 包的 sha256 值。
尽管格式和有些文档中有差异，但是这种方法也是可以工作的。

注意camerarawpreviews等名称必须与 tar.gz 包的名称一致，否则无法安装。

如果你的设置正确，在管理设置 -> 概览中，应该没有报错。

常见问题的解决方案

Nix 把 Nextcloud 安装到哪里去了？

根据源码，默认的安装路径是/var/lib/nextcloud，数据目录是/var/lib/nextcloud/data。

找不到日志

默认情况下，NixOS 将 Nextcloud 的日志输出模式修改成了

Copy
'log_type' => 'syslog',
'loglevel' => '2',

在这种情况下，Nextcloud 的日志会输出到守护进程的日志中，可以使用journalctl -t Nextcloud查看。

有意思的是，似乎'loglevel' => '2'是无效配置。Nextcloud 内部的 Warning, Error, 甚至 Fatal 都被视为 Debug 输出。所以可能需要将'loglevel' => '2'改成'loglevel' => '0'。

Copy
services.nextcloud = {
[...]
logLevel = 0;
};

如果需要，可以附加参数-f实时查看日志。

应用商店在哪里？

默认情况下，NixOS 安装的 Nextcloud 没有应用商店。

你可以设置appstoreEnable为true来启用应用商店。

Copy
services.nextcloud = {
[...]
appstoreEnable = true;
};

无法发送邮件

由于设计缺陷，无法通过 Nix 文件直接配置邮件发送，必须使用extraConfig来配置。

Copy
services.nextcloud = {
[...]
extraOptions = {
mail_smtpmode = "smtp";
smtpsecure = "ssl";
mail_sendmailmode = "smtp";
mail_from_address = "nextcloud";
mail_domain = "example.com";
mail_smtphost = "smtp.example.com";
mail_smtpport = "465";
mail_smtpauth = 1;
mail_smtpname = "nextcloud@example.com";
mail_smtppassword = "password";
};
};

以上配置来源于config.php文件，你可以在一个全新的 Nextcloud 实例中找到这些配置。

在本地搭建测试服务器时，似乎无论采用什么设置也不能发送邮件，但是在云服务器上（如 AWS）却可以正常发送邮件。这个问题似乎是由于本地网络环境导致的，我没有找到解决方案。

Nix 配置文件示例

这里给出IPFS 链接

需要注意，一些设置使用了占位符代替，所以不要直接使用这个配置文件。

主要的修改有：

Copy
services.nextcloud = {
enable = true;
hostName = "nextcloud.nixos";
config = {
dbtype = "pgsql";
dbuser = "nextcloud";
dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself
dbname = "nextcloud";
adminpassFile = "/path/to/your/nextcloud/adminpass.txt"; # Replace with your own path
adminuser = "root";
};
package = pkgs.nextcloud26;
extraApps = {
contacts = pkgs.nextcloud26Packages.apps.contacts;
mail = pkgs.nextcloud26Packages.apps.mail;
calendar = pkgs.fetchNextcloudApp rec {
url = "https://github.com/nextcloud-releases/calendar/releases/download/v4.3.4/calendar-v4.3.4.tar.gz";
sha256 = "0pj1h86kdnckzfrn13hllgps4wa921z4s24pg5d2666fqx89rwrv";
};
# More configuration can be found in My IPFS share
};
extraOptions = {
# Replace below with your own mail server settings
mail_smtpmode = "smtp";
smtpsecure = "ssl";
mail_sendmailmode = "smtp";
mail_from_address = "system";
mail_dmoain = "example.com";
mail_smtphost = "smtp.example.com";
mail_smtpport = "465";
mail_smtpayth = 1;
mail_smtpname = "system@example.com";
mail_smtppassword = "password";
};
};

services.postgresql = {
enable = true;
ensureDatabases = [ "nextcloud" ];
ensureUsers = [
{ name = "nextcloud";
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
}
];
};

systemd.services."nextcloud-setup" = {
requires = ["postgresql.service"];
after = ["postgresql.service"];
};

networking.firewall.allowedTCPPorts = [ 80 443 465 587 ];

维护

刚刚搭建没多久，所以还没有遇到什么维护上的问题。如果有问题，我会在这里更新。

对于大问题，我可能会单独写一篇文章，在解决问题的那篇博文放上这个博文的链接，在这里放上指向解决方案的链接。

如果想要及时收到更新，可以在区块链上关注我的博客。