Reverse Proxy Configuration
There is no built-in authentication or authorization. You must use a reverse proxy with authentication if accessing from outside your local network. Exposing the server directly to the internet allows anyone to access, modify, and delete all your data.
Network Restriction
At minimum, ensure Mahresources only binds to localhost:
# In your .env or command line
BIND_ADDRESS=127.0.0.1:8181
This prevents direct external access even if your firewall is misconfigured.
Nginx with Basic Authentication
Install Nginx and Create Password File
# Install nginx and apache2-utils (for htpasswd)
sudo apt install nginx apache2-utils
# Create password file
sudo htpasswd -c /etc/nginx/.htpasswd yourusername
Nginx Configuration
Create /etc/nginx/sites-available/mahresources:
server {
listen 80;
server_name mahresources.example.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name mahresources.example.com;
# SSL certificates (use Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/mahresources.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mahresources.example.com/privkey.pem;
# Basic authentication
auth_basic "Mahresources";
auth_basic_user_file /etc/nginx/.htpasswd;
# Increase body size for file uploads
client_max_body_size 2G;
location / {
proxy_pass http://127.0.0.1:8181;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts for large file uploads
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
}
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/mahresources /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Caddy
Caddy handles HTTPS certificates automatically.
Caddyfile
mahresources.example.com {
# Basic authentication
basicauth /* {
yourusername $2a$14$hashedpasswordhere
}
# Reverse proxy to Mahresources
reverse_proxy localhost:8181 {
# Increase timeouts for large uploads
transport http {
response_header_timeout 300s
}
}
# Increase request body limit for uploads
request_body {
max_size 2GB
}
}
Generate the password hash:
caddy hash-password
Traefik
Docker Compose with Traefik
services:
traefik:
image: traefik:v2.10
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=you@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik-certs:/letsencrypt
mahresources:
build: . # build from local Dockerfile
volumes:
- ./data/db:/data/db
- ./data/files:/data/files
environment:
- DB_TYPE=SQLITE
- DB_DSN=/data/db/mahresources.db
- FILE_SAVE_PATH=/data/files
- BIND_ADDRESS=:8181
labels:
- "traefik.enable=true"
- "traefik.http.routers.mahresources.rule=Host(`mahresources.example.com`)"
- "traefik.http.routers.mahresources.entrypoints=websecure"
- "traefik.http.routers.mahresources.tls.certresolver=letsencrypt"
- "traefik.http.services.mahresources.loadbalancer.server.port=8181"
# Basic auth middleware
- "traefik.http.routers.mahresources.middlewares=mahresources-auth"
- "traefik.http.middlewares.mahresources-auth.basicauth.users=yourusername:$$apr1$$hashedpass"
volumes:
traefik-certs:
Generate the password hash for Traefik:
# Install htpasswd
sudo apt install apache2-utils
# Generate hash (note: escape $ as $$ in docker-compose)
htpasswd -nb yourusername yourpassword
SSE (Server-Sent Events) Configuration
The download queue and plugin job system use Server-Sent Events at /v1/jobs/events and /v1/download/events. Reverse proxies must disable response buffering for these endpoints, or SSE messages will be delayed until the buffer fills.
Nginx
Add a location block for the SSE endpoints:
location ~ ^/v1/(jobs|download)/events$ {
proxy_pass http://127.0.0.1:8181;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Disable buffering for SSE
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400s;
chunked_transfer_encoding off;
}
Caddy
Caddy passes SSE events without buffering by default. No extra configuration is needed.
Traefik
Add response buffering middleware to the SSE routes:
labels:
- "traefik.http.middlewares.sse-buffering.buffering.maxResponseBodyBytes=0"
Alternative Authentication Methods
OAuth2 Proxy
For more advanced authentication (Google, GitHub, etc.), consider using OAuth2 Proxy:
# Example with Google OAuth
oauth2-proxy \
--upstream=http://127.0.0.1:8181 \
--http-address=0.0.0.0:4180 \
--provider=google \
--client-id=123456789-abcdef.apps.googleusercontent.com \
--client-secret=GOCSPX-abc123def456ghi789 \
--email-domain=yourdomain.com
Authelia
For self-hosted SSO, Authelia provides two-factor authentication and user management.
Security Checklist
- Mahresources binds only to localhost (
127.0.0.1:8181) - Reverse proxy requires authentication for all requests
- HTTPS is enabled with valid certificates
- Strong passwords are used for basic auth
- Firewall blocks direct access to port 8181
- Regular security updates are applied