Guide for installation of [[https://nextcloud.com|Nextcloud]].
== Create database ==
Postgresql should work, but Nextcloud recommends MySQL. See [[MemberManual/Databases#Create_a_Database]]. We'll assume you name the database `${USER}_cloud`.
== Software installation ==
=== Unpack ===
Get the Nextcloud tarball from [[https://nextcloud.com/install/#instructions-server|Nextcloud]].
Pick a directory where you'll host Nextcloud, for example `$HOME/www/next.your.domain`. We'll call it `$NEXTDIR`.
Also pick a directory for data, for example `$HOME/var/nextcloud`. We'll call it `$NEXTDATA`.
Unpack the source.
{{{
unzip nextcloud-15.0.0.zip
}}}
Move the resulting `nextcloud` directory to where you decided to have the document root.
{{{
mv nextcloud $NEXTDIR
}}}
Create an empty data directory in the document root. This is necessary for the duration of the installation, we'll delete it later.
{{{
cd $NEXTDIR
mkdir data
}}}
=== Permissions ===
Adjust directory permissions:
{{{
fsr setacl . system:anyuser none
fsr sa . $USER.daemon rlk
fsr sa config $USER.daemon rlidwk
fsr sa data $USER.daemon rlidwk
fsr sa apps $USER.daemon rlidwk
}}}
=== Patch ===
Delete some lines in the file `core/Migrations/Version14000Date20180129121024.php`. This doesn't play well with the HCoop default of not granting DROP on tables. The easiest fix seems to be to manually drop these later.
{{{
@@ -49,11 +49,6 @@
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
- $schema->dropTable('admin_sections');
- $schema->dropTable('admin_settings');
- $schema->dropTable('personal_sections');
- $schema->dropTable('personal_settings');
-
return $schema;
}
}
}}}
=== Create real data directory ===
Create the data directory and give it correct permissions:
{{{
mkdir $NEXTDATA
cd $NEXTDATA
fsr setacl . system:anyuser none
fsr sa . $USER.daemon rlidwk
}}}
== Nextcloud installation wizard ==
Open up the web site, which should now show you the installation wizard. Fill it out like so:
{{{
Data folder: $NEXTDATA
Database: MySQL/MariaDB
Username: whatever you like
Password: likewise
DB hostname: mysql
}}}
== Post-installation configuration ==
=== Neater URLs ===
Add this line to `$NEXTDIR/config/config.php`:
{{{
cd $NEXTDIR
php7.2 occ config:system:set htaccess.RewriteBase --type=string --value="/"
php7.2 occ maintenance:update:htaccess
}}}
The second command should not be necessary, but it will generate a correct `.htaccess` for your version, which you can compare to the domtool setup below.
'''TODO: Still struggling with some of the related rewrite rules. Remove this section if I can't get it to work.'''
=== Update some column types ===
Run this command to convert a couple of column types that are not handled by the installer:
{{{
cd $NEXTDIR
php7.2 occ db:convert-filecache-bigint
}}}
=== Set DB charset ===
In the MySQL CLI, run:
{{{
ALTER DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
}}}
Run these Nextcloud CLI commands:
{{{
php7.2 occ config:system:set mysql.utf8mb4 --type boolean --value="true"
php7.2 occ maintenance:repair
php7.2 occ maintenance:mode --off
}}}
=== Cache ===
Add this line to `$NEXDIR/config/config.php`, to enable the APCu cache:
{{{
'memcache.local' => '\OC\Memcache\APCu',
}}}
=== Cron ===
Add a [[MemberManual/UsingCron|cron job]] like this replacing the variables with your username/path:
{{{
*/5 * * * * k5start -qtUf /etc/keytabs/user.daemon/$USER -- /usr/bin/php7.2 -f $NEXTDIR/cron.php
}}}
== Domtool ==
For reference here is the `.htaccess` set up by Nextcloud 15, if `htaccess.RewriteBase` is set to `/`:
{{{
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
SetEnvIfNoCase Authorization "(.+)" HTTP_AUTHORIZATION=$1
# Add security and privacy related headers
Header set X-Content-Type-Options "nosniff"
Header set X-XSS-Protection "1; mode=block"
Header set X-Robots-Tag "none"
Header set X-Download-Options "noopen"
Header set X-Permitted-Cross-Domain-Policies "none"
Header set Referrer-Policy "no-referrer"
SetEnv modHeadersAvailable true
# Add cache control for static resources
Header set Cache-Control "max-age=15778463"
# Let browsers cache WOFF files for a week
Header set Cache-Control "max-age=604800"
php_value upload_max_filesize 511M
php_value post_max_size 511M
php_value memory_limit 512M
php_value mbstring.func_overload 0
php_value always_populate_raw_post_data -1
php_value default_charset 'UTF-8'
php_value output_buffering 0
SetEnv htaccessWorking true
php_value upload_max_filesize 511M
php_value post_max_size 511M
php_value memory_limit 512M
php_value mbstring.func_overload 0
php_value default_charset 'UTF-8'
php_value output_buffering 0
SetEnv htaccessWorking true
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} DavClnt
RewriteRule ^$ /remote.php/webdav/ [L,R=302]
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L]
RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L]
RewriteRule ^\.well-known/webfinger /public.php?service=webfinger [QSA,L]
RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
RewriteRule ^remote/(.*) remote.php [QSA,L]
RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
RewriteRule ^(?:\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
AddType image/svg+xml svg svgz
AddEncoding gzip svgz
DirectoryIndex index.php index.html
AddDefaultCharset utf-8
Options -Indexes
ModPagespeed Off
#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####
ErrorDocument 403 /
ErrorDocument 404 /
Options -MultiViews
RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg)$
RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$
RewriteCond %{REQUEST_FILENAME} !core/img/manifest.json$
RewriteCond %{REQUEST_FILENAME} !/remote.php
RewriteCond %{REQUEST_FILENAME} !/public.php
RewriteCond %{REQUEST_FILENAME} !/cron.php
RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php
RewriteCond %{REQUEST_FILENAME} !/status.php
RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php
RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php
RewriteCond %{REQUEST_FILENAME} !/robots.txt
RewriteCond %{REQUEST_FILENAME} !/updater/
RewriteCond %{REQUEST_FILENAME} !/ocs-provider/
RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
RewriteRule . index.php [PT,E=PATH_INFO:$1]
RewriteBase /
SetEnv front_controller_active true
DirectorySlash off
}}}
This can be translated to this Domtool config:
{{{
web "cloud" where
PhpVersion = php72;
DocumentRoot = home "$NEXTDIR";
SSL = use_cert "/etc/apache2/ssl/user/your.cert.pem";
with
location "/" with
unset_options [indexes, multiViews];
directoryIndex ["index.php", "index.html"];
end;
expiresByType "text/css" access 1 weeks;
expiresByType "application/javascript" access 1 weeks;
expiresByType "image/svg" access 1 weeks;
expiresByType "image/gif" access 1 weeks;
expiresByType "application/font-woff2" access 1 weeks;
setEnvIfNoCase "^Authorization$" "(.+)" ["XAUTHORIZATION=$1"];
rewriteCond "%{HTTP_USER_AGENT}" "DavClnt" [];
rewriteRule "^$" "/remote.php/webdav/" [redirectWith temp, last];
rewriteRule ".*" "-" [env "HTTP_AUTHORIZATION" "%{HTTP:Authorization}"];
rewriteRule "^\.well-known/host-meta" "/public.php?service=host-meta" [qsappend, last];
rewriteRule "^\.well-known/host-meta\.json" "/public.php?service=host-meta-json" [qsappend, last];
rewriteRule "^\.well-known/webfinger" "/public.php?service=webfinger" [qsappend, last];
rewriteRule "^\.well-known/carddav" "/remote.php/dav/" [redirectWith permanent, last];
rewriteRule "^\.well-known/caldav" "/remote.php/dav/" [redirectWith permanent, last];
rewriteRule "^remote/(.*)" "remote.php" [qsappend, last];
rewriteRule "^(?:build|tests|config|lib|3rdparty|templates)/.*" "-" [redirectWith notfound, last];
rewriteCond "%{REQUEST_URI}" "!^/\.well-known/(acme-challenge|pki-validation)/.*" [];
rewriteRule "^(?:\.|autotest|occ|issue|indie|db_|console).*" "-" [redirectWith notfound, last];
end;
}}}
And to enforce SSL:
{{{
web "cloud" with
rewriteRule "^(.*)$" "https://cloud.elektrubadur.se$1" [redirectWith permanent];
end;
}}}
'''TODO: Work out how to set up the additional rewrites needed to remove the 'index.php' bit from URLs.'''
== Login ==
You should now be able to log in and look around Nextcloud. You may want to have a look at `Settings → Overview` for any warnings. You will see a bunch of warnings like this:
{{{
Some app directories are owned by a different user than the web server one. This may be the case if apps have been installed manually. Check the permissions of the following app directories:
/afs/hcoop.net/user/…
}}}
These can be ignored.
== Configuration in Nextcloud UI ==
=== cron ===
Go to ''Settings → Basic Settings'' and select the option ''Cron'' under ''Background jobs'' (since we set that up earlier).
You can check this page to ensure your cronjob is working.
=== Mail notifications ===
In ''Settings → Basic Settings'', set:
{{{
Send mode: Sendmail
Sendmail mode: pipe (-t)
From address: whatever@your.domain
}}}
'''TODO: Update with instructions on using SMTP when that's working.'''
== Cleanup ==
=== Delete default data directory ===
Since we use a new data directory we can delete the one in the document root:
{{{
cd $NEXTDIR
rm -r data
}}}
=== Drop unused tables ===
We should drop those deprecated tables from before (this wasn't actually working for me, will look into how to drop tables in MySQL later).
{{{
mysql-fixperms
mysql -h mysql -p ${USER}_cloud
DROP TABLE admin_sections;
DROP TABLE admin_settings);
DROP TABLE personal_sections;
DROP TABLE 'personal_settings;
}}}
'''TODO: This didn't work for me, fix the instructions on dropping tables.'''