498 lines
14 KiB
YAML
498 lines
14 KiB
YAML
---
|
|
# 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-<your-outpost-name>.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
|
|
---
|
|
# 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
|
|
initContainers:
|
|
# Configure proxy auth in database before starting
|
|
- name: configure-auth
|
|
image: filebrowser/filebrowser:v2.54.0
|
|
command:
|
|
- sh
|
|
- -c
|
|
- |
|
|
# Create database if it doesn't exist and configure proxy auth
|
|
if [ ! -f /config/filebrowser.db ]; then
|
|
echo "Creating new database with proxy auth..."
|
|
filebrowser config init --database /config/filebrowser.db
|
|
fi
|
|
echo "Setting proxy authentication..."
|
|
filebrowser config set --database /config/filebrowser.db --auth.method=proxy --auth.header=X-authentik-username
|
|
echo "Configuration complete"
|
|
volumeMounts:
|
|
- name: config
|
|
mountPath: /config
|
|
securityContext:
|
|
runAsUser: 1000
|
|
runAsGroup: 1000
|
|
containers:
|
|
- name: filebrowser
|
|
image: filebrowser/filebrowser:v2.54.0
|
|
command:
|
|
- filebrowser
|
|
- --database=/config/filebrowser.db
|
|
- --root=/srv
|
|
- --port=80
|
|
- --address=0.0.0.0
|
|
ports:
|
|
- containerPort: 80
|
|
name: http
|
|
protocol: TCP
|
|
env:
|
|
- name: TZ
|
|
value: "Europe/Budapest"
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /srv
|
|
- name: config
|
|
mountPath: /config
|
|
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
|
|
---
|
|
# 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;
|
|
# Fix redirects behind reverse proxy
|
|
absolute_redirect off;
|
|
|
|
# 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;
|
|
|
|
# Prevent search engine indexing
|
|
add_header X-Robots-Tag "noindex, nofollow, noarchive" always;
|
|
|
|
# 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 |