Setup nextcloud with nginx in ubuntu

Problem

You want to setup NextCloud with Nginx. But Nextcloud doesn’t officially support Nginx, its go-to server is Apache.

Please note that webservers other than Apache 2.x are not officially supported.

– Nextcloud Doc

Solution

To run with Nginx, you need to install the php-fpm first, then proxy all php requeste through the fpm unix domain socket.

Step 1

1
2
apt update
apt install php7.2 php7.2-fpm php7.2-mysql php7.2-xml php7.2-zip php7.2-mbstring php7.2-gd php7.2-curl

Now go to /etc/php/ folder, you should be able to see the “7.2” folder.

Step 2

Change php-fpm running user:group. Go to /etc/php/7.2/fpm/pool.d, edit the “www.conf" file. Change the “user” and “group” to the user you want, e.g. “nobody”, “nogroup”.

Then restart fpm:

1
$ service php7.2-fpm restart

Step 3

You could now check the fpm’s running UDS at path: /var/run/php/php-fpm.sock. Change its permission if needed.

Now setup your nginx config:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
upstream nextcloud-handler {
server unix:/var/run/php/php-fpm.sock;
}

server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl;
server_name yourdomain.com;

ssl_certificate /path/to/fullchain.cer;
ssl_certificate_key /path/to/yourdomain.key;

# HTTP response headers borrowed from Nextcloud `.htaccess`
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;
add_header X-Frame-Options "SAMEORIGIN";

fastcgi_hide_header X-Powered-By;

#### config log file
error_log /path/to/nextcloud_logs/nginx-err.log warn;
access_log /path/to/nextcloud_logs/nginx-access-$year$month$day.log combined;
#### end of config log file

// if you only allow certain IPs to access
allow 127.0.0.1;
allow 67.65.102.103;
deny all;

client_max_body_size 1024M;
fastcgi_buffers 64 4K;

gzip off;

root /path/to/nextcloud/folder;

location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 /remote.php/webdav/$is_args$args;
}
}

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

location ^~ /.well-known {
# The rules in this block are an adaptation of the rules
# in `.htaccess` that concern `/.well-known`.

location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }

location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
location /.well-known/pki-validation { try_files $uri $uri/ =404; }

# Let Nextcloud's API for `/.well-known` URIs handle all other
# requests by passing them to the front-end controller.
return 301 /index.php$request_uri;
}

location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }

# if you want to change shared files' access
# shared file in nextcloud will start with /index.php/s/
# so here we add "allow all" for this path
location ~ ^/index.php/s/ {
allow all;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;

try_files $fastcgi_script_name =404;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;

fastcgi_param modHeadersAvailable true;
fastcgi_pass nextcloud-handler;

fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}

location ~ \.php(?:$|/) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;

try_files $fastcgi_script_name =404;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;

fastcgi_param modHeadersAvailable true;
fastcgi_pass nextcloud-handler;
# uncomment the next line if you don't want to show "index.php" in the url
# fastcgi_param front_controller_active true;

fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}

location ~ \.(?:css|js|svg|gif|png|jpg|ico)$ {
try_files $uri /index.php$request_uri;
expires 6M; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
}

location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
}

# Rule borrowed from `.htaccess`
location /remote {
return 301 /remote.php$request_uri;
}

location / {
try_files $uri $uri/ /index.php$request_uri;
}
}

Others

After you config this and restart nginx, if nginx show 500 error but didn’t log anywhere, to debug, you can just go to your nextcloud folder, find the index.php file, then before each line where throw the 500 error, just add echo to print that error out in the webpage. For example:

1
2
echo $ex;
OC_Template::printExceptionErrorPage($ex, 500);

Remember to remove these lines after you found the error and fixed it.

Reference: