I'm having several issues setting up Payload cms behind an Nginx Proxy for production. Basically my admin user is getting a lot of 403 Forbidden responses from the API, like . Doing some tests I console logged my req, and user variables in the update access hook of a collection, both resulting in undefined. Log-in to admin works, but log-out is weird.
Sometimes, even https://site.com/api/access
returns {"errors":[{"message":"req is not defined"}]}
Here´s my configuration file with of course redacted sensitive information
Nginx configuration
server {
root /var/www/site/dist;
index index.html index.htm index.nginx-debian.html;
server_name site.com www.site.com;
# Static Root
location / {
try_files $uri $uri/ /index.html;
}
# Payload API
location /api {
proxy_pass http://localhost:1336/api;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
proxy_set_header Host $host;
}
# Payload Admin Dashboard
location /admin {
proxy_pass http://localhost:1336/admin;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
# Socket.IO
location /socket.io {
proxy_pass http://localhost:1336/socket.io;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
# proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
payload.config.js
import { buildConfig } from 'payload/config';
import path from 'path';
// Globals
import Setup from './globals/Setup';
import Avatars from './globals/Avatars';
// Collections
import Admins from './collections/Admins';
import Users from './collections/Users';
import Achievements from './collections/Achievements';
import Experiences from './collections/Experiences';
import Spaces from './collections/Spaces';
import Playlists from './collections/Playlists';
import Images from './collections/Images';
import Videos from './collections/Videos';
import Categories from './collections/Categories';
import Sections from './collections/Sections'
// Graphics
import Logo from './graphics/Logo';
import Icon from './graphics/Icon';
export default buildConfig({
serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL,
cors: '*',
admin: {
user: Admins.slug,
css: path.resolve(__dirname, './styles/style.scss'),
scss: path.resolve(__dirname, './styles/vars.scss'),
meta: {
favicon: '/public/favicon.png'
},
components: {
graphics: {
Logo,
Icon,
},
},
},
debug: process.env.PAYLOAD_PUBLIC_DEBUG,
globals: [
Setup,
Avatars,
],
collections: [
Categories,
Sections,
Spaces,
Experiences,
Playlists,
Images, Videos,
Users,
Achievements,
Admins
// Add Collections here
],
plugins: [],
localization: {
locales: [
'en',
'es',
],
defaultLocale: 'en',
fallback: true,
},
});
.env
MONGODB_URI=mongodb://user:pass@127.0.0.1:27017/db?authSource=admin
PAYLOAD_SECRET=MYSECRET
PAYLOAD_CONFIG_PATH=src/payload.config.js
PAYLOAD_PUBLIC_SERVER_URL=http://localhost:1336
PAYLOAD_PUBLIC_PORT=1336
PAYLOAD_PUBLIC_DEBUG=FALSE
NODE_ENV=PRODUCTION
Thanks @jmikrut I finally found the error on my side. Given I was using a reverse proxy I thought the Payload serverUrl still had to be localhost:1337. For anyone reading, given the way I configured my payload.config.js, this is the .env that finally worked for me, pay attention to PAYLOAD_PUBLIC_SERVER_URL and PAYLOAD_PUBLIC_PORT
Production Deploy .env
MONGODB_URI=mongodb://user:pass@127.0.0.1:27017/db?authSource=admin
PAYLOAD_SECRET=MYSECRET
PAYLOAD_CONFIG_PATH=src/payload.config.js
PAYLOAD_PUBLIC_SERVER_URL=https://mysite.com
PAYLOAD_PUBLIC_PORT=1336
PAYLOAD_PUBLIC_DEBUG=FALSE
NODE_ENV=PRODUCTION
Local development .env
MONGODB_URI=mongodb://user:pass@127.0.0.1:27017/db?authSource=admin
PAYLOAD_SECRET=MYSECRET
PAYLOAD_CONFIG_PATH=src/payload.config.js
PAYLOAD_PUBLIC_SERVER_URL=https://localhost:3000
PAYLOAD_PUBLIC_PORT=3000
PAYLOAD_PUBLIC_DEBUG=TRUE
Ah yep. Good call. This makes perfect sense. Happy to hear that you solved it and thank you for following up!
Hey @gonzam88 — we've seen similar issues before and it is related to your auth cookie(s) being rejected.
Do you have any cookie options configured on your admins
collection? Generally this issue is due to you having a problem with specifying secure cookies, but not using HTTPS, or trying to use cross-domain cookies which are now rejected in newer versions of popular browsers.
A way to check why a cookie is being rejected is to open the Inspector in Chrome, go to the Network tab, and then log in to the admin UI. You should try and find the login
network POST
request. Click that request, and see if there is a little yellow "warning" symbol next to the Set-Cookie
header of that request.
Here is a screenshot of a working login request within our demo admin panel:
Hi @jmikrut thanks for the reply. My cookie looks fine 🍪 yet req is still undefined. Any other place to look? Thanks in advanced.
OK. Can you send the full error message that you're seeing regarding req
being undefined? We've never seen that before..
Also, I'm not sure if it's related (don't see how it would be) but generally we just have one location
block within our nginx
reverse proxy configs, like this:
server {
server_name website.com;
location / {
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
fyi I tried this configuration just in case but got the same result
The thing with the nginx configuration is I need my static vue site running on / and then payload on both /admin and /api. I could be wrong, or maybe there's a better approach way but this worked for me before with other CMSs.
There's actually no error displayed, I just can't edit docs with my admin users unless my access is
update: ({ req: { user } }) => { return true },
If I try a rule where only admin users can edit like the following I get the typical You are not allowed to perform this action
const adminsAndEditors = async ({ req: { user } }) => {
if (!user) return false // return false to deny a user
if(user.collection == 'admins') return true // every admin can edit
}
Let me know if there's any other info I can provide.
[19:15:30] ERROR (payload): Forbidden: You are not allowed to perform this action.
at new ExtendableError (/var/www/testing-douob-server-payload/node_modules/payload/src/errors/APIError.ts:26:11)
at new APIError (/var/www/testing-douob-server-payload/node_modules/payload/src/errors/APIError.ts:43:5)
at new Forbidden (/var/www/testing-douob-server-payload/node_modules/payload/src/errors/Forbidden.ts:6:5)
at executeAccess (/var/www/testing-douob-server-payload/node_modules/payload/src/auth/executeAccess.ts:9:43)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at Payload.create (/var/www/testing-douob-server-payload/node_modules/payload/src/collections/operations/create.ts:74:5)
at Payload.create (/var/www/testing-douob-server-payload/node_modules/payload/src/collections/requestHandlers/create.ts:14:17)
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.