Hi n8n Community,
Goal: I need to embed my self-hosted n8n instance (running on a Hostinger VPS at https://n8n.<scrubbed_for_privacy>.hstgr.cloud) into an iframe on a page served from my local development environment (http://localhost:3500).
Problem: Authentication within the iframe fails because the n8n-auth session cookie, served from the Hostinger VPS, is consistently being set with SameSite=Lax. This prevents it from being used in the cross-domain iframe context on localhost. I need it to be SameSite=None; Secure.
My Setup:
- n8n Server: Hosted on a Hostinger VPS.
- n8n Version:
1.85.4(also tested1.79.0with the same result) - Deployment: Docker Compose on the Hostinger VPS.
- Reverse Proxy: Traefik v2.x (running on the same Hostinger VPS, handling routing and Let’s Encrypt SSL termination for
n8n.<scrubbed_for_privacy>.hstgr.cloud)
Configuration & Troubleshooting Attempted: I’ve configured the following environment variables for the n8n service (running on the Hostinger VPS) and confirmed they are set correctly inside the running container using docker exec:
N8N_PROTOCOL=httpsN8N_SECURE_COOKIE=true(TheSecureflag is correctly present on theSet-Cookieresponse header)N8N_PROXY_HOPS=1(This resolved the Express ‘trust proxy’ warning)N8N_SESSION_COOKIE_SAMESITE=None(Set this hoping it would control the attribute, butSameSite=Laxpersists. I also could not find this specific variable documented.)
My Question: What is the correct/supported method in n8n (specifically v1.85.4 or recent) to ensure the session cookie is set with SameSite=None; Secure to allow for cross-domain iframe embedding (from localhost to the Hostinger-hosted n8n)?
Is there a different environment variable, is N8N_SESSION_COOKIE_SAMESITE perhaps functional under different conditions (or bugged), or must this modification currently have to be handled externally by the reverse proxy (Traefik on the Hostinger server)?
Thanks for any help or clarification!
adding docker-compose thats been santized to remove domain/email
version: “3.7”
services:
traefik:
image: “traefik:latest”
container_name: traefik
restart: always
command:
- “–api=true”
- “–api.insecure=true” # Note: Consider securing this in production
- “–providers.docker=true”
- “–providers.docker.exposedbydefault=false”
- “–entrypoints.web.address=:80”
- “–entrypoints.web.http.redirections.entryPoint.to=websecure”
- “–entrypoints.web.http.redirections.entrypoint.scheme=https”
- “–entrypoints.websecure.address=:443”
- “–certificatesresolvers.mytlschallenge.acme.tlschallenge=true”
# Use a placeholder for the email address
- “--certificatesresolvers.mytlschallenge.acme.email=your-email@example.com”
- “–certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json”
ports:
- “80:80”
- “443:443”
volumes:
- traefik_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro # Standard Docker socket mount
n8n:
# Using latest or a specific version (e.g., n8nio/n8n:1.85.4)
image: n8nio/n8n:latest
container_name: n8n
restart: always
# Port exposed only to the host’s loopback (for Traefik)
ports:
- “127.0.0.1:5678:5678”
labels:
- “traefik.enable=true”
# Use a placeholder for the domain/hostname
- “traefik.http.routers.n8n.rule=Host(n8n.yourdomain.com)”
- “traefik.http.routers.n8n.entrypoints=web,websecure” # Or just websecure if redirect is reliable
- “traefik.http.routers.n8n.tls=true”
- “traefik.http.routers.n8n.tls.certresolver=mytlschallenge”
- “traefik.http.routers.n8n.middlewares=n8n-headers@docker” # Corrected middleware reference name potentially
# Define security headers middleware (adjust middleware name if needed)
- "traefik.http.middlewares.n8n-headers.headers.customResponseHeaders.Content-Security-Policy=frame-ancestors http://localhost:3500;" # Allows iframe from localhost
- "traefik.http.middlewares.n8n-headers.headers.SSLRedirect=true" # May be redundant with entrypoint redirect
- "traefik.http.middlewares.n8n-headers.headers.STSSeconds=315360000" # Consider a standard value like 31536000 (1 year)
- "traefik.http.middlewares.n8n-headers.headers.browserXSSFilter=true"
- "traefik.http.middlewares.n8n-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.n8n-headers.headers.forceSTSHeader=true"
# Removed SSLHost - generally not needed when Traefik handles TLS correctly for the domain
# - "traefik.http.middlewares.n8n.headers.SSLHost=n8n.yourdomain.com"
- "traefik.http.middlewares.n8n-headers.headers.STSIncludeSubdomains=true"
- "traefik.http.middlewares.n8n-headers.headers.STSPreload=true"
environment:
# Use 0.0.0.0 or omit for N8N_HOST when behind proxy
# - N8N_HOST=0.0.0.0
- N8N_PORT=5678
- N8N_PROTOCOL=https # n8n knows it's behind HTTPS
# Use a placeholder for the domain/hostname
- WEBHOOK_URL=https://n8n.yourdomain.com/
- N8N_API_ALLOW_ORIGIN=* # Be cautious with wildcard in production
# N8N_SECURITY_HEADER_X_FRAME_OPTIONS=ALLOWALL # Removed, use CSP instead
- NODE_ENV=production # Use 'production'
- GENERIC_TIMEZONE=UTC # Set as needed
- N8N_CORS_ENABLED=true
# N8N_SESSION_COOKIE_SAMESITE=None # Removed as it was found ineffective/undocumented
# Add proxy hops setting if needed (based on previous discussion)
- N8N_PROXY_HOPS=1
# Add secure cookie setting if needed (based on previous discussion)
- N8N_SECURE_COOKIE=true
volumes:
- n8n_data:/home/node/.n8n # Standard internal n8n path
# Use a placeholder for the host path if sharing /local-files
- /path/on/host:/files
volumes:
traefik_data:
n8n_data: