Introduction
In this article, I am presenting you my security concept for accessing a self-hosted Nextcloud server, using FortiGate firewall port forwarding and an Apache-based proxy server.
Nextcloud is a powerful solution for hosting your private data, offering complete control over your files and personal information, and it is very important to properly secure it.
My Security Concept with FortiGate Firewall

Incoming traffic first passes through a FortiGate firewall, which has specific ports open. The firewall forwards this traffic to a proxy server running on Apache Web Server.
The proxy server then routes the requests intended for Nextcloud to the Nextcloud server itself, ensuring seamless access while isolating the Nextcloud server from direct exposure to the internet. This layered approach enhances security and provides better traffic management.
I don’t have a dedicated public IP address and instead share a single address for multiple services (Immich, Nextcloud, WordPress Web Page). As a result, using a proxy server becomes a necessity to manage and route traffic to the appropriate services.
You can check the security of your Nextcloud installation on this link. As you can see, my setup got an A+ rating 🙂

Open Ports on FortiGate Needed for Nextcloud and Nextcloud Talk
I use Nextcloud through its web interface, Android and iPhone, as well as the Nextcloud Talk feature. To ensure these services function correctly, specific ports need to be opened:
Open Ports on FortiGate for Nextcloud
- Port 443 (HTTPS): Used for secure access to the Nextcloud web interface and API.
- Port 80 (HTTP): Temporarily required for SSL certificate issuance/renewal. This port should be closed afterward to reduce the attack surface → It is my recommendation!
At this link you can find how to open a port on FortiGate firewall.
Open Ports on FortiGate for Nextcloud Talk
- Port 3478 (UDP): Used for TURN server communication (without this port, WebRTC-based audio and video calls will not work properly)
- You can find more information about the required open ports for the Nextcloud Talk application at this link.
Configuration Port Forwarding in CLI on FortiGate Firewall
Here is an example of how port forwarding is done on a FortiGate device:
config firewall vip
edit "TO-NEXTCLOUD-TALK"
set extip 192.168.1.253 --> Replace with your external address
set extintf "any"
set portforward enable
set mappedip "192.168.10.41" --> Replace with your Nextcloud Server address
set protocol udp
set extport 3478
set mappedport 3478
next
Configuration for Port Forwarding in GUI on FortiGate Firewall
You can configure port forwarding in GUI. Policy & Objects
-> Virtual IPs

If you are not sure how to configure port forwarding you can check more details on the following link.
FortiGate Traffic Forwarding and Security Profiles
On FortiGate firewall, I use policies specifically configured to forward traffic destined for Nextcloud to the proxy server. These policies include dedicated Security Profiles for:
- IPS (Intrusion Prevention System)
- Application Control to inspect and filter the traffic thoroughly.
At this screenshot, you can see FortiGate Incoming Policy and below CLI configuration:

config firewall policy
edit 59
set name "toProxy"
set srcintf "wan1"
set dstintf "internal"
set srcaddr "all"
set dstaddr "TO-PROXY-443"
set action accept
set schedule "flat-rate"
set service "ALL"
set utm-status enable
set fsso disable
set av-profile "default"
set ips-sensor "protect_http_server-strong"
set application-list "block-high-risk"
set ssl-ssh-profile "certificate-inspection"
next
Security Concept: FortiGate IPS (Intrusion Prevention System)
The IPS profile monitors incoming and outgoing traffic for potential threats, such as exploits or malicious activity, ensuring that only safe connections are allowed through.
My configuration you can see on screenshots below and CLI config:

config ips sensor
edit "protect_http_server-strong"
set comment "Blocks all Critical/High/Medium and some Low severity vulnerabilities"
set block-malicious-url enable
config entries
edit 4
set rule 29519
set status enable
set action block
set rate-count 5
set rate-duration 10
set quarantine attacker
set quarantine-expiry 7d
next
edit 6
set rule 20940
set status enable
set action block
set rate-count 60
next
edit 7
set rule 35662
set status enable
set action block
set rate-count 5
set rate-duration 10
set quarantine attacker
set quarantine-expiry 1d
next
edit 8
set rule 12090
set status enable
set action block
set rate-count 500
next
edit 9
set rule 20945
set status enable
set action block
set rate-count 200
set rate-duration 10
next
edit 10
set rule 40839
set status enable
set action block
set rate-count 18
set rate-duration 1
next
edit 11
set rule 20954
set status enable
set action block
set rate-count 60
set quarantine attacker
set quarantine-expiry 7d
next
edit 12
set rule 24072
set status enable
set action block
set rate-count 5
set rate-duration 10
next
edit 13
set rule 32059
set status enable
set action block
set rate-count 1000
set rate-duration 1
next
edit 14
set rule 28634
set status enable
set action block
set rate-count 35
set rate-duration 1
next
edit 16
set rule 40130
set status enable
set action block
set rate-count 5
set rate-duration 2
next
edit 17
set rule 33106
set status enable
set action block
set rate-count 3
set rate-duration 3
set quarantine attacker
set quarantine-expiry 7d
next
edit 18
set rule 39292
set status enable
set action block
set rate-count 15
set rate-duration 1
next
edit 19
set rule 37047
set status enable
set action block
set rate-count 100
set rate-duration 1
next
edit 20
set rule 20946
set status enable
set action block
set rate-count 60
set rate-duration 10
next
edit 21
set rule 38623
set status enable
set action block
set rate-count 10
set rate-duration 2
next
edit 1
set severity medium high critical
set status enable
set log-packet enable
set action block
next
edit 22
set rule 22909
set status enable
set action block
set rate-count 200
set rate-duration 10
next
edit 5
set location server
set protocol HTTP HTTPS
set status enable
set log-packet enable
set action block
next
edit 23
set rule 17991
set status enable
set action block
set rate-count 275
set rate-duration 1
next
edit 15
set location server
set protocol HTTPS
set application Apache
set status enable
set log-packet enable
set action block
next
edit 24
set protocol HTTPS
set os Linux
set status enable
set action block
next
end

This layered inspection process ensures that any malicious activity is intercepted at the firewall level, adding a security layer before traffic even reaches the proxy server or Nextcloud environment.
By combining these security measures, I maintain a robust and secure setup for accessing my Nextcloud services.
Security Concept: FortiGate Application Control
Application Control profile detects and regulates applications being accessed, blocking unauthorized or risky apps from reaching the proxy or Nextcloud server. In this case, standard categories are used, and I choose to block “risky” one.
My configuration you can see on screenshots below:

config application list
edit "block-high-risk"
set unknown-application-log enable
config entries
edit 1
set application 12290 17244 27948
set action pass
set log disable
next
edit 2
set application 16492 42533
set action pass
next
edit 3
set application 42537 43349
next
edit 4
set category 2 6
next
edit 5
set action pass
next
end