Lighttpd Nextcloud config

I have non as well. Nextcloud runs fine without though. Just put your data dir outside of web root just in case.

I still stick with apache2 on my RPi2. Takes a bid more memory but 1 GB is enough for traffic a RPi can handle anyway. If you are low in memory you can try low mem Distro like DietPi where I contribute btw :wink:.

Hey, I’m also interested if somebody improved some configs.

I’ll start working on my own setup the next few days, so get in touch with me if you want to know whether I managed or if you have a nice setup.

.well-known Cal/CardDAV redirect, if Nextcloud is in a subdir of webroot, accessible via At least a start :smile::

cat /etc/lighttpd/conf-available/99-dav_redirect.conf

# Redirect Cal/CardDAV requests to Nextcloud endpoint:
url.redirect = (
	"^/.well-known/caldav"  => "/nextcloud/remote.php/dav",
	"^/.well-known/carddav" => "/nextcloud/remote.php/dav"

lighttpd-enable-mod dav_redirect

The following can be used to allow pretty URLs:
url.rewrite-if-not-file = ( "^/nextcloud/([^.]+)/?$" => "/nextcloud/index.php/$1" )
€: Breaks at least updater, which needs to be taken out from this rewrite, similar to what is done in official Nginx config:
Properly more issues, since if-not-file does not work as expected: "^/nextcloud/(.+)/?$" leads to remote.php requests (files/activity list) being rewritten/blocked somehow, only "^/nextcloud/([^.]+)/?$" works, which explicitly excludes URL with dots inside. But since it does not reliable detect remote.php existence, it might break other things as well, or you need to define rewrites separately for all dirs/file types, similar to what is done in Nginx config above.

mod_rewrite needs to be enabled:
lighttpd-enable-mod rewrite
server.modules += ( "mod_rewrite" )
somewhere in Lighttpd config, if above command does not work on your system.

But does not work with this, in comparison with Apache .htacces/rewrite base solution or Nginx config from docs with enabled front controller:

  • The links inside Nextcloud web UI always revert the pretty URLs. Not sure how to enable Nextcloud to use pretty URLs internally as well, since on Nginx this is the automatically just via webserver config.
  • App store does not open with pretty URL, just blank page. I guess has something to do with Nextcloud internally using non-pretty URLs and /settings/apps is also contained when accessing a certain apps page (files, activity, …).[/nextcloud]/apps/files/ e.g. is redirected to default app, where the rewrite rule should actually rewrite it to /index.php/settings/apps (app store). So Nextcloud internal rewrite/redirects somehow break this. Investigating…

Enable referrer policy:
setenv.add-response-header = ( "Referrer-Policy" => "no-referrer" )

Requires mod_setenv:
server.modules += ("mod_setenv" )

€: NC15 ships this header internally now it seems. Adding it leads to warning on admin panel (I guess since set doubled), removing it resolves the warning. Not sure why on Apache, it is added via .htaccess as well then without issues. In Nginx config from docs, it is added, but removed from PHP scripts via: fastcgi_param modHeadersAvailable true;?

I ended up now using the following config for Lighttpd, which includes security hardenings from default .htaccess respectively Nginx config from docs:

$HTTP["url"] =~ "^/nextcloud($|/)" {

	# Hardening
	# - Directories
	$HTTP["url"] =~ "^/nextcloud/(build|tests|config|lib|3rdparty|templates|data)($|/)" { url.access-deny = ("") }
	# - Files
	$HTTP["url"] =~ "^/nextcloud/(\.|autotest|occ|issue|indie|db_|console)" { url.access-deny = ("") }
	# - Directory listing = "disable"
	# - Cache control and security headers for static resources
	$HTTP["url"] =~ "^/nextcloud/\.(css|js|woff2?|svg|gif)$" {

		setenv.add-response-header += (

			"Cache-Control" => "public, max-age=15778463",
			"X-Content-Type-Options" => "nosniff",
			"X-XSS-Protection" => "1; mode=block",
			"X-Robots-Tag" => "none",
			"X-Download-Options" => "noopen",
			"X-Permitted-Cross-Domain-Policies" => "none",
			"Referrer-Policy" => "no-referrer",



1 Like

Thanks for sharing!
I hope you don’t mind I added this info here:

To be true, I am not 100% sure, but I should have made this by myself, based on official Apache and Nginx configs, otherwise I would have linked the actual source. Since it is identical to what you have linked, probably it is the other way round :smile:.
€: Ah sorry, I misunderstood, you meant YOU added the info there, right? Jep for sure it is free to use and spread in the hope being useful for others :+1:.

Here the current version that we use in DietPi btw:

I found that caching of static content didn’t work as expected, especially due to the many queries falling out of the regex.
I’m now playing with mod_expire and

server.modules += ("mod_expire")       

$HTTP["url"] =~ "^/(own|next)cloud/(.+\.(css|woff2|js|png|jpg|bmp|ico|svg)\??.*)$" {
    expire.url = ( "" => "access plus 365 days" )    
    setenv ...

This seems to cache a lot more…

EDIT: the URL already has the query part cut off, so it should be

$HTTP["url"] =~ "^/(own|next)cloud/(.+\.(css|woff2|js|png|jpg|bmp|ico|svg))$" {

Does this include images and such served by Nextcloud?
I mean Nextcloud is PHP-based, so all content is served via PHP, and AFAIK caching is done via the memcache.local provider defined in config.php, APCu at best (php-apcu).

Caching defined in the webserver configs AFAIK should only have an effect when manually/directly accessing files via URL path relative to webroot, so outside of PHP.

Ah okay there is the "Cache-Control" => "public, max-age=15778463",, so this should indeed then have an effect, most likely for button graphics and things like that.
Hmm when you see the Nginx config provided by Nextcloud docs, e.g. jpg and some other file types are explicitly taken out for the regex, but handled in a separate block (which is not required on Lighttpd):
Same for the default .htaccess for Apache.

Don’t ask me why it is like this, but I guess there is some reason. But we could ask the devs why it is advised to not set the caching header for png, jpg, bmp etc as well.

I’d recommend to have a look at this [DISCUSSION] Web server settings and security checklist. This discussion contains information about Nextcloud instance running on the lighttpd web server on FreeBSD 11.

Hope you can find there answers to your questions.

1 Like

Many thanks for sharing. Sadly the caching header/settings are not discussed.

Good to know that I am not the only one that struggles with pretty URLs on Lighttpd. Actually the regex is not the issue, nor the rewrite rules. Only think I couldn’t figure out is how to make Nextcloud stay with pretty URLs, meaning that hitting any link will not have you going back to index.php based URL.

The effect of enabling browser cache for icons already makes a huge difference on a low power device such as the My Cloud EX2Ultra NAS. Caching JPG as well depends a bit on the use case: if the user never modifies his pictures (e.g. with Photoshop etc), you’re fine with cached thumbnails.

Here’s another interesting tutorial to tune lighttpd:

1 Like

Additional Lighttpd setting(s) on Lighttpd 1.4.5X:

Those URL parser options should be disabled all together since doubled decoding leads to inhabits CRFS tokens on GET requests.

I’ll do some PR for the docs with Lighttpd config when I find time.

Just landed here looking for something else. Too much to read and digest but I’ll just say I have Nextcloud 20 running under lighttpd on Ubuntu 20.04 and all is fine.

I was juts looking around for a Pretty URLs tip to save me the trouble of reinterpreting all the Apache assumptions in docs like these:

Happy to share my configs, though PM (personal message) is prefereable to public post on server configs IMHO.

That said I would be might curious if anyone could:

a) identify the URL rewrites NextCloud recommends for PrettyURLS (they suggest running occ maintenance:update:htaccess (see their help) , which alas does not write rules to .htaccess as it should on my system so I don’t even have an Apache reference.

b) Translate the Apache rules to lighttpd rules for us.

Clearly it’s easy to do rewrites, it’s knowing what. We can’t juts insert index.php into all incoming URLs now, that will break a load of other URLs (not least remote.php ones etc) and Nextcloud support PrettyURLs so have a canonical list of redirects they maintain, they’re just not sharing them as information, instead providing tips for Apache users on how to install them without seeing them.

It would be nice if Nextcloud published a canonical list of redirects to achieve Pretty URLs in a server agnostic fashion … we can convert that to any syntax, if we can understand the needs, what URLs to add index.php to and what ones not to.

They also don’t describe anywhere to my satisfaction if there’s a way to ask fro internal URLs to be generated without the index.php (once you have the redircts in place). There are these two suggestions:

  • ‘overwrite.cli.url’
  • ‘htaccess.RewriteBase’

and the former looks great but applies to CLI only and the second is not documented clearly so I searched the code base and couldn’t find any evidence of its being used anywhere alas.

Hey there,

just reading all the posts here.
My lighttpd.conf is running fine on a raspberry pi. Only problems are using IPv6 config as the website is not reachable afterwards.

Here is my config, hope it helps:>

server.modules = (
#       "mod_auth", --> already in etc/lighttpd/conf-available/05-auth.conf

server.document-root        = "/var/www/html"
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
server.errorlog             = "/var/log/lighttpd/error.log"             = "/var/run/"
server.username             = "www-data"
server.groupname            = "www-data"
server.bind                 = ""
server.port                 = 80
server.dir-listing          = "enable"
#server.use-ipv6             = "enable" --> disabled as IPv6 is not working well yet                 = "<your-webserver-address>"

alias.url = ("/.well-known/" => "/etc/lighttpd/certbot/.well-known/")

# strict parsing and normalization of URL for consistency and security
# (might need to explicitly set "url-path-2f-decode" = "disable"
# if a specific application is encoding URLs inside url-path)
server.http-parseopts = (
  "header-strict"            => "enable",# default
  "host-strict"              => "enable",# default
  "host-normalize"           => "enable",# default
  "url-normalize"            => "enable",# default
  "url-normalize-unreserved" => "enable",# recommended highly
  "url-normalize-required"   => "enable",# recommended
  "url-ctrls-reject"         => "enable",# recommended
  "url-path-2f-decode"       => "enable",# recommended highly (unless breaks app)
 #"url-path-2f-reject"       => "enable",
  "url-path-dotseg-remove"   => "enable",# recommended highly (unless breaks app)
 #"url-path-dotseg-reject"   => "enable",
  "url-query-20-plus"        => "enable",# consistency in query string

index-file.names            = ( "index.php", "index.html", "index.lighttpd.html" )
url.access-deny             = ( "~", ".inc" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

compress.cache-dir          = "/var/cache/lighttpd/compress"
compress.filetype           = ( "application/javascript", "text/css", "text/html", "text/plain" )

# default listening port for IPv6 falls back to the IPv4 port
include_shell "/usr/share/lighttpd/ " + server.port
include_shell "/usr/share/lighttpd/"
include "/etc/lighttpd/conf-enabled/*.conf"

# IPv4
# Redirect HTTP to HTTPS
$HTTP["scheme"] == "http" {
    $HTTP["host"] =~ ".*" {
            url.redirect = (".*" => "https://%0$0")

$SERVER["socket"] == ":443" {
    include "ssl.conf"
    accesslog.filename = "/var/log/lighttpd/<your-webserver-address>/saccess.log"

## Setting up two headers ###
setenv.add-response-header = ( "X-Whom" => "lighttpd-aws-us-east" )
setenv.add-response-header += ( "Strict-Transport-Security" => "max-age=15768000; includeSubdomains; preload"  )

server.modules += (

Hope this helps for comparison.

Also I put some ssl-stuff in another file “ssl.conf” here:>

ssl.engine = "enable"
ssl.acme-tls-1 = "/etc/lighttpd/dehydrated/tls-alpn-01"
ssl.openssl.ssl-conf-cmd = ("Protocol" => "-ALL, TLSv1.2, TLSv1.3")
ssl.privkey= "/etc/letsencrypt/live/<your-webserver-address>/privkey.pem"
ssl.pemfile= "/etc/letsencrypt/live/<your-webserver-address>/cert.pem" "/etc/letsencrypt/live/<your-webserver-address>/chain.pem"

This website helped my quite a bit for setting up nextcloud and letsencrypt:

Best regards

Thanks for sharing. Yes generally Lighttpd works pretty fine for Nextcloud, also the URL parser options got a fix so that they do not break Nextcloud session tokens in the query string.

It is not an issue to translate the pretty URL rewrites either from .htaccess (after applying pretty URLs like you would do with Apache2) or from the Nginx config in the docs, they function. What I didn’t manage is to get the Nextcloud internal URL builder to as well build pretty URLs for internal redirects and links. They stay “ugly”, and with that it doesn’t make much sense to apply them.

First of all, thanks a lot for this topic. I’ve been running Nextcloud on my Lighttpd server for some years now without any major issues, without having had any specific settings in my config. I was able to get rid of those .well-known warnings in the overview thanks to you guys though, and also applied the hardening tweaks.

I was wondering, has anyone successfully set up a Collabora Online Development Edition (CODE) server with Lighttpd as reverse proxy? I was trying to get it working yesterday but wasn’t able to. I was able to get Nextcloud to recognize the service and claim that it was working, but it didn’t open in the browser when opening a file. The loolwsd log was saying things like this:

ERR  Unknown resource: /xxxxxxx/loleaflet.html?WOPISrc=https%3A%2F%2F<myurl.tld>%2Fnc%2Findex.php%2Fapps%2Frichdocuments%2F%2Ffiles%2F2<userID>&title=<filename>&lang=en&closebutton=1&revisionhistory=1 , host: <myurl.tld>, path: 3
loolwsd[680281]: [0] 'xxxxxx'
loolwsd[680281]: [1] 'loleaflet.html'
loolwsd[680281]: [2] 'WOPISrc=https%3A%2F%2F<myurl.tld>%2Fnc%2Findex.php%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F<userID>&title=<filename>&lang=en&closebutton=1&revisionhistory=1'
loolwsd[680281]: full URI: /xxxxxxx/loleaflet.html?WOPISrc=https%3A%2F%2F<myurl.tld>%2Fnc%2Findex.php%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F2<userID>&title=<filename>&lang=en&closebutton=1&revisionhistory=1| wsd/LOOL>

I’m guessing my proxy server settings wasn’t correct. I have since deleted them from my config, but I was basically just guessing as to what would work based on the nginx and apache examples from this site and trying different things to no avail. If anyone has had success with this and knows a working config I would be very grateful.

To add something else to this topic, Lighttpd recently (in 1.4.56) enabled HTTP/2 support. It will be enabled by default in a future release but you can enable it manually currently by adding this to your config, as per the release notes:

server.feature-flags += ("server.h2proto" => "enable", "server.h2c" => "enable")

This could potentially speed up Nextcloud a bit more. Nextcloud recommends using HTTP/2 in their docs.

1 Like

Many thanks for sharing. Just for the Raspberry Pi and Debian users: This means it will be available in the upcoming (this summer) Debian (and Raspbian) Bullseye release.