deck9 / input

A privacy-focused, no-code, open-source form builder designed for simplicity and brand consistency.
https://getinput.co
GNU Affero General Public License v3.0
162 stars 27 forks source link

Static Assets not fetched from APP_URL #123

Closed alexander-schoch-linuxdays closed 6 months ago

alexander-schoch-linuxdays commented 6 months ago

When self-hosting ghcr.io/deck9/input:main behind an nginx reverse proxy (port 443 forwarded to port 8080 in the container), static assets (.js and .css) are fetched from http://input:8080/build/app/assets/app-cd48a56c.js instead of https://$APP_URL/build/app/assets/app-cd48a56c.js.

Environment Variables:

DB_CONNECTION=mysql
DB_DATABASE=input
DB_HOST=[docker MariaDB service in same network]
DB_USERNAME=input_user
DB_PASSWORD=[password]
APP_URL=[domain]
PhilReinking commented 6 months ago

@alexander-schoch-linuxdays sounds like APP_URL from your .env is not recognized correctly. Can you share your Docker run command with me?

Usually, the default for APP_URL is localhost:8080, since your assets URLs are using input:8080 something must have set APP_URL to that value.

alexander-schoch-linuxdays commented 6 months ago

@PhilReinking

I started the application as a service in docker swarm using the following command:

docker service create --replicas 1 --name input --network cluster --env DB_CONNECTION=mysql --env DB_DATABASE=input --env DB_HOST=mariadb --env DB_USERNAME=[username] --env DB_PASSWORD=[password] --env APP_URL=[domain] ghcr.io/deck9/input:main

The only thing that is actually set to "input" is the DB_DATABASE and the service name.

alexander-schoch-linuxdays commented 6 months ago

Also, maybe the reason is the nginx config:

server {
    server_name [domain];
    client_max_body_size 100M;
    location / {
        resolver 127.0.0.11 ipv6=off;
        proxy_pass http://input:8080;
    }

    listen [::]:443 ssl;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/[domain]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[domain]/privkey.pem;
}

server {
    server_name [domain];

    listen 80;
    listen [::]:80;

    client_max_body_size 100M;

    return 301 https://$host$request_uri;
}
alexander-schoch-linuxdays commented 6 months ago

Update on this issue:

The input from the wrong host comes from the docker service name and is set by nginx in the line proxy_pass http://input:8080. Setting proxy_set_header Host $host; , like below, resolves this.

server {
    server_name [domain];
    client_max_body_size 100M;
    location / {
        resolver 127.0.0.11 ipv6=off;
        proxy_pass http://input:8080;
                proxy_set_header Host $host;
    }

    listen [::]:443 ssl;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/[domain]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[domain]/privkey.pem;
}

server {
    server_name [domain];

    listen 80;
    listen [::]:80;

    client_max_body_size 100M;

    return 301 https://$host$request_uri;
}

However, there's a new problem now: Input tries to fetch all static files via http, but the browser blocks it due to origin policy when accessing input via https (it works with http though). I am still figuring out on how to fix this.

alexander-schoch-linuxdays commented 6 months ago

Alright, I got it to work. For anyone also having this problem, this is the nginx config that worked for me:

server {
    server_name [domain];
    location / {
        resolver 127.0.0.11 ipv6=off;
        proxy_pass http://[docker service name]:8080;
        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;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    listen [::]:443 ssl;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/[domain]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[domain]/privkey.pem;
}

server {
    server_name [domain];

    listen 80;
    listen [::]:80;

    return 301 https://$host$request_uri;
}
PhilReinking commented 6 months ago

@alexander-schoch-linuxdays Thanks for debugging this. I will improve the docs about running Input behind a proxy.