--- # FileBrowser - Web-based file manager # https://filebrowser.org/ # # Features: # - Web-based file browser and manager # - File upload/download via web UI # - File preview (images, text, markdown, video) # - Built-in text editor # - Share links for files # - Very lightweight (~15MB RAM) # - Authentik SSO integration (proxy auth) # # Authentication: Via Authentik (no double login!) # FileBrowser trusts the X-authentik-username header from the proxy. # # Authentik Setup: # 1. Create a Proxy Provider in Authentik: # - Name: FileBrowser # - Authorization flow: default-provider-authorization-implicit-consent # - Type: Forward auth (single application) # - External host: https://webadmin.dooplex.hu # # 2. Create an Application: # - Name: FileBrowser # - Slug: filebrowser # - Provider: FileBrowser (the one you just created) # # 3. Create an Outpost (or add to existing): # - Name: filebrowser-outpost # - Type: Proxy # - Integration: Kubernetes (auth-system namespace) # - Applications: FileBrowser # # 4. Authentik will auto-create: # - Deployment: ak-outpost-filebrowser-outpost in auth-system # - Service: ak-outpost-filebrowser-outpost in auth-system # - Ingress for /outpost.goauthentik.io path on webadmin.dooplex.hu # # Note: The outpost service name in auth-url must match! # If you name outpost differently, update the annotation: # http://ak-outpost-.auth-system.svc.cluster.local:9000/... # # Access: # - Admin UI: https://webadmin.dooplex.hu (Authentik login) # - Public files: https://web.dooplex.hu (direct file access, no auth) # # Usage for static HTML hosting: # 1. Login to webadmin.dooplex.hu (via Authentik) # 2. Upload HTML files and assets to /public folder # 3. Access directly via web.dooplex.hu/filename or web.dooplex.hu/folder # # Clean URL examples: # - /public/fizetes.html → web.dooplex.hu/fizetes # - /public/fizetes/index.html → web.dooplex.hu/fizetes # - /public/about/index.html → web.dooplex.hu/about # # Note: First user to login via Authentik becomes admin in FileBrowser. # Additional users logging in will be created automatically. # apiVersion: v1 kind: Namespace metadata: name: web-system labels: app.kubernetes.io/name: web-system --- # PVC for files apiVersion: v1 kind: PersistentVolumeClaim metadata: name: filebrowser-data namespace: web-system labels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser recurring-job-group.longhorn.io/backup: enabled spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 5Gi --- # PVC for database and config apiVersion: v1 kind: PersistentVolumeClaim metadata: name: filebrowser-config namespace: web-system labels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 100Mi --- # ConfigMap for FileBrowser settings apiVersion: v1 kind: ConfigMap metadata: name: filebrowser-config namespace: web-system labels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser data: .filebrowser.json: | { "port": 80, "baseURL": "", "address": "", "log": "stdout", "database": "/config/filebrowser.db", "root": "/srv", "auth": { "method": "proxy", "header": "X-authentik-username" } } --- # FileBrowser Deployment apiVersion: apps/v1 kind: Deployment metadata: name: filebrowser namespace: web-system labels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser template: metadata: labels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser spec: securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 containers: - name: filebrowser image: filebrowser/filebrowser:v2.53.1 ports: - containerPort: 80 name: http protocol: TCP args: - --auth.method=proxy - --auth.header=X-authentik-username env: - name: TZ value: "Europe/Budapest" volumeMounts: - name: data mountPath: /srv - name: config mountPath: /config - name: settings mountPath: /.filebrowser.json subPath: .filebrowser.json resources: requests: cpu: 10m memory: 32Mi limits: cpu: 500m memory: 128Mi livenessProbe: httpGet: path: /health port: http initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /health port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 volumes: - name: data persistentVolumeClaim: claimName: filebrowser-data - name: config persistentVolumeClaim: claimName: filebrowser-config - name: settings configMap: name: filebrowser-config --- # Service for FileBrowser apiVersion: v1 kind: Service metadata: name: filebrowser namespace: web-system labels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser spec: type: ClusterIP ports: - port: 80 targetPort: http protocol: TCP name: http selector: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser --- # Ingress for FileBrowser admin UI (Authentik protected) apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: filebrowser namespace: web-system labels: app.kubernetes.io/instance: filebrowser app.kubernetes.io/name: filebrowser annotations: cert-manager.io/cluster-issuer: letsencrypt-prod external-dns.alpha.kubernetes.io/hostname: webadmin.dooplex.hu nginx.ingress.kubernetes.io/proxy-body-size: "1024m" nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/ssl-redirect: "true" # Authentik forward auth - update outpost name after creating in Authentik! nginx.ingress.kubernetes.io/auth-url: http://ak-outpost-filebrowser-outpost.auth-system.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx nginx.ingress.kubernetes.io/auth-signin: https://webadmin.dooplex.hu/outpost.goauthentik.io/start?rd=$escaped_request_uri nginx.ingress.kubernetes.io/auth-response-headers: X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid nginx.ingress.kubernetes.io/auth-snippet: | proxy_set_header X-Forwarded-Host $http_host; spec: ingressClassName: nginx-internal tls: - hosts: - webadmin.dooplex.hu secretName: filebrowser-tls rules: - host: webadmin.dooplex.hu http: paths: - path: / pathType: Prefix backend: service: name: filebrowser port: name: http - host: webadmin.home http: paths: - path: / pathType: Prefix backend: service: name: filebrowser port: name: http --- # ============================================ # NGINX Static File Server (Public Access) # ============================================ # This serves files from /public folder without authentication # Access: https://web.dooplex.hu/filename or https://web.dooplex.hu/folder # apiVersion: apps/v1 kind: Deployment metadata: name: static-server namespace: web-system labels: app.kubernetes.io/instance: static-server app.kubernetes.io/name: static-server spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: static-server app.kubernetes.io/name: static-server template: metadata: labels: app.kubernetes.io/instance: static-server app.kubernetes.io/name: static-server spec: securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 initContainers: # Create public directory if it doesn't exist - name: init-public-dir image: busybox:1.36 command: ['sh', '-c', 'mkdir -p /srv/public && chmod 755 /srv/public'] volumeMounts: - name: data mountPath: /srv securityContext: runAsUser: 0 containers: - name: nginx image: nginx:1.27-alpine ports: - containerPort: 8080 name: http protocol: TCP volumeMounts: - name: data mountPath: /usr/share/nginx/html subPath: public readOnly: true - name: nginx-config mountPath: /etc/nginx/nginx.conf subPath: nginx.conf resources: requests: cpu: 5m memory: 16Mi limits: cpu: 100m memory: 64Mi livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 5 periodSeconds: 30 readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 3 periodSeconds: 10 volumes: - name: data persistentVolumeClaim: claimName: filebrowser-data - name: nginx-config configMap: name: static-server-config --- # ConfigMap for nginx static server apiVersion: v1 kind: ConfigMap metadata: name: static-server-config namespace: web-system labels: app.kubernetes.io/instance: static-server app.kubernetes.io/name: static-server data: nginx.conf: | user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /tmp/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; # Temp paths for non-root user client_body_temp_path /tmp/client_temp; proxy_temp_path /tmp/proxy_temp; fastcgi_temp_path /tmp/fastcgi_temp; uwsgi_temp_path /tmp/uwsgi_temp; scgi_temp_path /tmp/scgi_temp; server { listen 8080; server_name _; root /usr/share/nginx/html; index index.html index.htm; # Health check endpoint location /health { access_log off; return 200 "OK\n"; add_header Content-Type text/plain; } # Serve static files location / { try_files $uri $uri/ $uri.html =404; # Directory listing disabled for security # Uncomment below if you want to browse directories # autoindex on; # autoindex_exact_size off; # autoindex_localtime on; # Cache static assets location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ { expires 7d; add_header Cache-Control "public, immutable"; } } # Security headers add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN; } } --- # Service for static server apiVersion: v1 kind: Service metadata: name: static-server namespace: web-system labels: app.kubernetes.io/instance: static-server app.kubernetes.io/name: static-server spec: type: ClusterIP ports: - port: 80 targetPort: 8080 protocol: TCP name: http selector: app.kubernetes.io/instance: static-server app.kubernetes.io/name: static-server --- # Ingress for public static files apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: static-server namespace: web-system labels: app.kubernetes.io/instance: static-server app.kubernetes.io/name: static-server annotations: cert-manager.io/cluster-issuer: letsencrypt-prod external-dns.alpha.kubernetes.io/hostname: web.dooplex.hu spec: ingressClassName: nginx-internal tls: - hosts: - web.dooplex.hu secretName: static-server-tls rules: - host: web.dooplex.hu http: paths: - path: / pathType: Prefix backend: service: name: static-server port: name: http - host: web.home http: paths: - path: / pathType: Prefix backend: service: name: static-server port: name: http