Self-Hosting Filebrowser with Nginx Proxy Manager, Docker, and Cloudflare
Welcome to a complete walkthrough of how I set up a secure, user-friendly self-hosted Filebrowser instance using Docker, Portainer, Nginx Proxy Manager (NPM), and Cloudflare DNS. This guide includes pitfalls, permissions issues, volume struggles, and what I learned along the way.
We wanted two separate users with access to their own folders β one for private storage and another for sharing files with friends. Everything had to be controllable via Portainer Web GUI, with minimal CLI interaction where possible (except DietPi).
π§ Objectives
- Run Filebrowser with separate folders for two users: user1 and user2
- Secure the setup with HTTPS via Cloudflare and Nginx Proxy Manager
- Access via CNAME: ftp.muminkis.com
- Use DietPi for CLI work and Portainer for web GUI container management
β Initial DietPi Prep
I used DietPi as my lightweight OS and did most system-level tasks via SSH:
sudo mkdir -p /srv/user1 /srv/user2
sudo chown -R 1002:1002 /srv
sudo chmod -R 775 /srvThis ensured each user folder was owned by the right UID/GID (1002 in my case). I skipped creating Linux users since Filebrowser manages its own access.
π Docker Volume Setup β The Real Struggle
This was by far the most frustrating part.
β What Went Wrong
- Mixing up bind mounts and Docker-managed volumes in Portainer
- Accidentally mounting /filebrowser.db directly instead of using /database
- Getting permission denied and is a directory errors when creating users
- Leaving behind orphaned anonymous volumes
β The Fix
I wiped it clean and used the CLI:
docker volume rm $(docker volume ls -qf dangling=true)Then ran the container:
docker run -d \
--name filebrowser \
-v /srv:/srv \
-v filebrowser_data:/database \
-p 8088:80 \
filebrowser/filebrowser:latest
This way, Filebrowser stores its DB in /database/filebrowser.db β persistent and accessible.
π€ Adding Filebrowser Users (from a temporary container)
docker run --rm -it \
--entrypoint sh \
-v /srv:/srv \
-v filebrowser_data:/database \
filebrowser/filebrowser:latest
Then:
filebrowser -d /database/filebrowser.db config init
filebrowser -d /database/filebrowser.db users add user1 --scope /srv/user1
filebrowser -d /database/filebrowser.db users add user2 --scope /srv/user2
filebrowser -d /database/filebrowser.db users update user1 --perm.adminπ Domain & Reverse Proxy Setup (NPM + Cloudflare)
- Cloudflare CNAME: Pointed ftp.muminkis.com to my public IP
- Nginx Proxy Manager:
- Scheme: http
- Forward Hostname/IP: dietpi
- Forward Port: 8088
- Cache Assets: β Off
- Websockets Support: β On
- Block Common Exploits: β On
SSL tab:
- Force SSL: β On
- HTTP/2 Support: β On
- HSTS Enabled: β On
- HSTS Subdomains: β On (since all subdomains are also covered)
π Security Extras
- Didn't use an Access List for Vaultwarden since my IP changes
- Did not enable SSL passthrough since the containers donβt have intern
β Final Thoughts
While setting up Filebrowser should be simple, doing it properly with volumes, secure access, user scoping, and proper cleanup was not trivial. But now:
- I can securely access two isolated folders via HTTPS
- I manage it easily via Portainer
- Everything is reproducible
Tip: Always test things manually in DietPi CLI when the web UI doesnβt work as expected.
Next steps:
- Add backups for /database volume
- Consider auto-renewal and alerts for SSL certs
- Monitor logs via Portainer or DietPi journal
Happy hosting! π