Hey guys,
So I've setup payload to run over https://domainx.dev through an nginx proxy.
In my .env (ecosystem.config.js) I've got "SERVER_URL": "https://domainx.dev",
.
In nginx I'm doing proxy_pass http://localhost:3000;
When I got to https://domainx.dev/api/pages
I get a result, but when I go to https://domainx.dev/admin
I get Cannot GET /admin
.
This does work without production mode.
Any tips? I'm slowly giving up hope 🤯
Answered by @jmikrut.
A new problem arised, but the initial problem is resolved.
Ah, figured it out! Thanks for the steps here.
To determine where the
build
files are, we are currently doing the following:path.resolve(process.cwd(), 'build')In your case, you're running the server in production directly from the
dist
folder rather than from an npm script or similar from the root folder. This also causes you to need to duplicate your.env
file to thedist
folder when normally you shouldn't need to do that.I think what we can do is improve the way that we are finding the
build
folder, rather than relying onprocess.cwd()
like that, which will make this more bulletproof. But in the meantime, you could adjust yourpm2
script to execute using thecwd
set to the root of the Payload folder. That will solve this!
Hey @falko100 —
Looks like there is a similar discussion here.
Here's what a typical NGINX config looks like when we deploy to production:
server {
index index.html;
server_name mywebsite.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;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = mywebsite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name mywebsite.com;
return 404; # managed by Certbot
}
One thing you could try is naming your SERVER_URL
environment variable to PAYLOAD_PUBLIC_SERVER_URL
. By default, Payload does not expose ANY environment variables to the admin panel for security reasons. Instead, we only expose variables prefixed with PAYLOAD_PUBLIC_
. Here are some docs about this.
I'm not sure, but if your NGINX config looks similar to ours, maybe your SERVER_URL has something to do with your issue.
Last thing I'd check: can you serve in production locally? Like, running build
and then serving locally? You may be having a Webpack error, where your admin panel is not successfully building. That would cause an /admin 404. You need to have successfully run yarn build
or similar before you can serve in production.
We'll figure it out!
Thanks for the quick reply. The main problem is that for some reason the admin panel route is secured in production mode. All other environment variables are send to my process.
We are running payload on 3000 and Nuxt on 8080.
server {
server_name dtm.coddin.dev;
location ~* /(cms|api|admin|__webpack_hmr|media) {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cache_bypass $http_upgrade;
}
location / {
proxy_pass http://localhost:8080;
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;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dtm.coddin.dev/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dtm.coddin.dev/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = dtm.coddin.dev) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name dtm.coddin.dev;
return 404; # managed by Certbot
}
Here is my pm2 config;
module.exports = {
apps : [
{
name: "frontend",
script: "./.output/server/index.mjs",
cwd: "./frontend",
watch: true,
env: {
"NODE_ENV": "production",
"PORT": 8080,
"NITRO_PORT": 8080,
"API_BASE_URL": "https://dtm.coddin.dev/api/"
}
},
{
name: "backend",
script: "./server.js",
cwd: "./backend/dist",
watch: true,
env: {
"NODE_ENV": "production",
"PORT": 3000,
"MONGODB_URI": "insert_correct_connection_url_here",
"PAYLOAD_SECRET": "I'm not gonna tell you my secret",
"SERVER_URL": "https://dtm.coddin.dev",
"PAYLOAD_PUBLIC_SERVER_URL": "https://dtm.coddin.dev",
"FRONTEND_URL": "https://dtm.coddin.dev",
"SMTP_HOST": "secret.hostname",
"SMTP_USER": "username",
"SMTP_PASS": "ssssh",
"SMTP_PORT": 1337
}
},
]
}
Have you ensured that you have built before serving in production? Do you have a ./build
folder on the server, with a properly built admin panel, including an index.html
file in it?
I just checked. There is a build folder with an index.html
and a lot of .js
an .woff
files.
Running the same server cd dist && node server.js
without NODE_ENV=production
the admin panel works.
OK. Can you rule out this being an NGINX config issue by just commenting out your entire Nuxt server block, and setting your first Payload location block like this?
location / {
// block config here
}
I'm sure sure. I have the same problem locally.
I'm gonna try with a clean payload install. Hold up 😁
Ah, figured it out! Thanks for the steps here.
To determine where the build
files are, we are currently doing the following:
path.resolve(process.cwd(), 'build')
In your case, you're running the server in production directly from the dist
folder rather than from an npm script or similar from the root folder. This also causes you to need to duplicate your .env
file to the dist
folder when normally you shouldn't need to do that.
I think what we can do is improve the way that we are finding the build
folder, rather than relying on process.cwd()
like that, which will make this more bulletproof. But in the meantime, you could adjust your pm2
script to execute using the cwd
set to the root of the Payload folder. That will solve this!
Ahh ok. I can do that, but then I get an error that the payload.config.js
is missing.
This can be solved by adding environment variable; PAYLOAD_CONFIG_PATH=dist/payload.config.js
Server works great now. Thanks @jmikrut for the help (and the amazing CMS, love it! ❤️)
Star
Discord
online
Get dedicated engineering support directly from the Payload team.