Architecture
The setup consists of multiple components working together. Nextcloud runs inside Docker, while Nginx is deployed directly on the host as a reverse proxy in front of the container. WireGuard provides VPN access and is managed usingwg-easy, which also runs in Docker. DNS and HTTPS proxying are handled by Cloudflare, with the domain configured as proxied.
This architecture allows the service to remain private to VPN users while still benefiting from Cloudflare features such as certificate management, DNS abstraction, and edge-layer protection.
Problem Statement
Cloudflare Masks Client IPs
When Cloudflare proxying is enabled, all incoming connections to Nginx appear to originate from Cloudflare IP addresses. As a result, Nginx does not see the real client IP by default. Traditional IP-based access control usingallow and deny directives therefore become ineffective, since every request appears to come from Cloudflare rather than the actual client.
VPN and Cloudflare Loopback Behavior
When a user connected to the WireGuard VPN accesseshttps://nextcloud.domain, the request exits the VPN tunnel, reaches Cloudflare, and is then routed back to the same server. In this scenario, Nginx sees the server’s own public IP address as the client IP instead of the WireGuard address. Without explicitly accounting for this behavior, legitimate VPN traffic would be denied.
Solution Overview
The solution consists of three coordinated steps:- Configure Nginx to trust Cloudflare and restore the real client IP.
- Enforce strict access control rules in the Nextcloud virtual host.
- Validate and apply the configuration changes safely.
1. Configure Nginx to Trust Cloudflare (Restore Real Client IP)
To make IP-based access control reliable, Nginx must be configured to trust Cloudflare and use theCF-Connecting-IP header as the authoritative source of the client IP. This is achieved by explicitly allowing Cloudflare’s published IP ranges and enabling Nginx’s real_ip module.
A dedicated configuration file was created at:
CF-Connecting-IP as the real client IP header. The following command was used to generate the file automatically:
2. Enforce Access Control in the Nextcloud Virtual Host
Once Nginx can reliably determine the real client IP, strict access control rules can be applied at the virtual host level. The Nextcloud site configuration was edited at:server {} block, the following rules were added:
3. Apply and Validate Changes
After updating the configuration, Nginx was tested and reloaded to safely apply the changes:Maintenance Considerations
If temporary or additional non-VPN access is required, an additionalallow x.x.x.x; directive can be added to the virtual host configuration, followed by an Nginx reload. This is useful for controlled maintenance or access from trusted static IPs.
Cloudflare IP ranges rarely change, but if access issues arise after extended periods of uptime, the Cloudflare IP fetch command can be rerun to refresh the trusted address ranges.
This configuration ensures that Nextcloud is accessible only to authenticated WireGuard VPN clients while preserving the operational and security benefits provided by Cloudflare. Real client IPs are correctly restored, VPN loopback behavior is explicitly handled, and all unintended public access paths are effectively blocked. The result is a secure, maintainable, and production-ready deployment suitable for environments with strict access control requirements.