Gozargah / Marzban

Unified GUI Censorship Resistant Solution Powered by Xray
https://t.me/gozargah_marzban
GNU Affero General Public License v3.0
3.79k stars 518 forks source link

502 Bad Gateway after update from v0.6.0 to v0.7.0 #1400

Open SegaSh99 opened 1 month ago

SegaSh99 commented 1 month ago

I use docker and set up docker compose config with Marzban and Traefik Proxy. On Marzban version 0.6.0 everything works, but after upgrading to version 0.7.0 I get an error I also used Nginx, which also returns an error When trying to open the image URL directly (http://172.18.0.4:8000/), I got HTTP ERROR 502

Machine details (please complete the following information):

ImMohammad20000 commented 1 month ago

hi send marzban logs

atomexpert commented 1 month ago

I use docker and set up docker compose config with Marzban and Traefik Proxy. On Marzban version 0.6.0 everything works, but after upgrading to version 0.7.0 I get an error I also used Nginx, which also returns an error When trying to open the image URL directly (http://172.18.0.4:8000/), I got HTTP ERROR 502

Machine details (please complete the following information):

  • OS: Ubuntu 22.04
  • Docker Compose version v2.27.0

Same problem. After installation the panel does not work

SerGioPicconti commented 1 month ago

People are you reading logs sometimes?

Since 0.7 release you need HTTPS (SSL) connection to panel to open it. It won't work anymore without secure connection. With https everything works great, including nginx. Buy some domain, use certbot and enjoy)

PrevikYT commented 1 month ago

so, how can i downgrade my panel

SegaSh99 commented 1 month ago

People are you reading logs sometimes?

Since 0.7 release you need HTTPS (SSL) connection to panel to open it. It won't work anymore without secure connection. With https everything works great, including nginx. Buy some domain, use certbot and enjoy)

image

nginx-1 | 2024/10/27 11:18:28 [error] 29#29: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.3, server: , request: "GET /dashboard HTTP/1.1", upstream: "http://172.19.0.2:8000/dashboard", host: "marzban.vpn.my-domain.ru"

SerGioPicconti commented 1 month ago

People are you reading logs sometimes? Since 0.7 release you need HTTPS (SSL) connection to panel to open it. It won't work anymore without secure connection. With https everything works great, including nginx. Buy some domain, use certbot and enjoy)

image

nginx-1 | 2024/10/27 11:18:28 [error] 29#29: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.3, server: , request: "GET /dashboard HTTP/1.1", upstream: "http://172.19.0.2:8000/dashboard", host: "marzban.vpn.my-domain.ru"

Provide nginx & marzban .env Looks like nginx config mismatch marzban port or ip or something else

SerGioPicconti commented 1 month ago

so, how can i downgrade my panel

You can install specific release if you want bash -c "$(curl -sL https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh)" @ install v0.6.0

SegaSh99 commented 1 month ago

Provide nginx & marzban .env

nginx:

server {
    listen 80;
    listen [::]:80;

    location / {
        proxy_pass http://marzban:8000;
        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 X-Forwarded-SSL on;
    }
}

.env: The rest of the variables are default (not changed)

# Main
# ----
PROJECT_NAME=marzban
DOMAIN=vpn.my-domain.ru

# Docker
# ------
COMPOSE_FILE=docker-compose.yml
DOCKER_MYSQL_PORT=12222

# MySQL
# ---------
MYSQL_DATABASE=marzban
MYSQL_USER=vpn
MYSQL_PASSWORD=vpn
MYSQL_ROOT_PASSWORD=vpn

# Web server configuration
UVICORN_HOST=0.0.0.0
UVICORN_PORT=8000

## We highly recommend add admin using `marzban cli` tool and do not use
## the following variables which is somehow hard codded infrmation.
SUDO_USERNAME="login"
SUDO_PASSWORD="pass"

docker compose:

services:
  traefik:
    image: traefik:3
    restart: on-failure
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/data/traefik.yml:/traefik.yml:ro
      - ./traefik/data/acme.json:/acme.json
      - ./traefik/configurations:/configurations:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.${PROJECT_NAME}-traefik.rule=Host(`traefik.${DOMAIN}`)"
      - "traefik.http.routers.${PROJECT_NAME}-traefik.service=api@internal"
      - "traefik.http.routers.${PROJECT_NAME}-traefik.middlewares=user-auth@file"
      - "traefik.http.routers.${PROJECT_NAME}-traefik.tls=true"
      - "traefik.http.routers.${PROJECT_NAME}-traefik.tls.certresolver=letsEncrypt"
    networks:
      - vpn
    ports:
      - "80:80"
      - "443:443"

  nginx:
    image: nginx:1.27-alpine
    restart: on-failure
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.${PROJECT_NAME}-nginx.rule=Host(`marzban.${DOMAIN}`)"
      - "traefik.http.routers.${PROJECT_NAME}-nginx.tls=true"
      - "traefik.http.routers.${PROJECT_NAME}-nginx.tls.certresolver=letsEncrypt"
    depends_on:
      - traefik
    networks:
      - vpn

  marzban:
    image: gozargah/marzban:latest
    restart: on-failure
    env_file: .env
    volumes:
      - /var/lib/marzban:/var/lib/marzban
    networks:
      - vpn

networks:
  vpn:
    driver: bridge

I added Nginx as an experiment, but you can directly direct traffic to the marzban container Both options do not work on version 0.7.0 https://traefik.vpn.my-domain.ru - is work https://marzban.vpn.my-domain.ru - 502 Bad Gateway

SerGioPicconti commented 1 month ago
server {
    listen **80**;
    listen [::]:**80**;

    location / {
        proxy_pass **http://marzban:8000**;
        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 X-Forwarded-SSL on;
    }
}

First of all, port 80 is for plain http, NOT HTTPS! Second - where did you get http://marzban host? Why? What for? It's just simple like http://127.0.0.1:8000

SerGioPicconti commented 1 month ago

And you don't need this DOMAIN=vpn.my-domain.ru if you use NGINX ssl config! And I hope you are not really using my-domain.ru because it's from some example and not for real use

SegaSh99 commented 1 month ago

First of all, port 80 is for plain http, NOT HTTPS! Second - where did you get http://marzban host? Why? What for? It's just simple like http://127.0.0.1:8000

http://marzban - This is the name of the container that needs to be proxy the request. Nginx is inside the container, so it works with port 80 Port 443 accepts traefik and forwards it to the container

SegaSh99 commented 1 month ago

And you don't need this DOMAIN=vpn.my-domain.ru if you use NGINX ssl config! And I hope you are not really using my-domain.ru because it's from some example and not for real use

SSL is set by traefik, not nginx

SegaSh99 commented 1 month ago

I downgraded to 0.6.0 and everything worked So don't write that my config is not working if you don't understand it

image

SerGioPicconti commented 1 month ago

First of all, port 80 is for plain http, NOT HTTPS! Second - where did you get http://marzban host? Why? What for? It's just simple like http://127.0.0.1:8000

http://marzban - This is the name of the container that needs to be proxy the request. Nginx is inside the container, so it works You wrote that you've tried nginx and it's also didn't worked!

As I can see you proxies port 443 to traefik, which must provide SSL connection from user to marzban host. If you have troubles with traefik - you must config it to redirect from port 80 to port 443 and proxy from port 443 to localhost:8000. For now it looks like you have wrong config and adding nginx config as you have priveded won't help you because it even doesn't have valid https proxy config! You have to down traefik container, set nginx config as it should be for https, and then it will work through nginx. Unfortunately what is traefik and how to config it (and, i'm really don't understant what is this for in your case) I don't know

SerGioPicconti commented 1 month ago

I downgraded to 0.6.0 and everything worked So don't write that my config is not working if you don't understand it

image

Это ты немного не понимаешь! У тебя не настроен нормальный конфиг через HTTPS, а начиная с 0.7 релиза без HTTPS марзбан больше не пашет! Поэтому у тебя и работает 0.6 релиз

Разберись в своей каше конфигов, настрой нормально nginx с использованием https и ssl и все спокойно заработает. Ты можешь зайти в ветку в телеге и посмотреть что все нормально поднимают https конфиги и юзают. Ты же зачем то навертел и траефик и nginx и еще и не настроил нормально. У тебя nginx кроме трафика НЕ https ничего не видит и не проксит - как он по твоему должен заработать??

SerGioPicconti commented 1 month ago

И разберись как работает проксирование на контейнеры... указание на http://marzban - с таким же успехом можешь по-русски написать - ничего как не работало так и не заработает!

SegaSh99 commented 1 month ago

Мне нужна комбинация traefik + marzban, без всяких nginx и прочего

M03ED commented 1 month ago

add this to your marzban docker file

    ports:
      - "127.0.0.1:3333:3333"

change port to your dashboard port

M03ED commented 1 month ago

and use 127.0.0.1 instead on 172.*

SerGioPicconti commented 1 month ago

Мне нужна комбинация traefik + marzban, без всяких nginx и прочего

Значит нужно настроить верно проксификацию 443 порта в траефике. 80 порт тут не нужен вообще

yaramahmadi commented 1 month ago
    ports:
      - "127.0.0.1:3333:3333"

I tried this solution, but it didn’t work for me.

Thank you.

M03ED commented 1 month ago

map this file to your docker something like this: then you should be able to use 172 range as uvicorn host if this worked i will merge it

volumes:
  - /var/lib/marzban:/var/lib/marzban   
  - /opt/marzban/main.py:/code/main.py
import click
import logging
import os
import ssl
import ipaddress

import uvicorn
from cryptography import x509
from cryptography.hazmat.backends import default_backend

from app import app, logger
from config import (DEBUG, UVICORN_HOST, UVICORN_PORT, UVICORN_SSL_CERTFILE,
                    UVICORN_SSL_KEYFILE, UVICORN_UDS)

def check_and_modify_ip(ip_address: str) -> str:
    """
    Check if an IP address is private. If not, return localhost.

    IPv4 Private range = [
        "192.168.0.0",
        "192.168.255.255",
        "10.0.0.0",
        "10.255.255.255",
        "172.16.0.0",
        "172.31.255.255"
    ]

    Args:
        ip_address (str): IP address to check

    Returns:
        str: Original IP if private, otherwise localhost

    Raises:
        ValueError: If the provided IP address is invalid, return localhost.
    """
    try:
        # Convert string to IP address object
        ip = ipaddress.ip_address(ip_address)

        if ip.is_private:
            return ip_address
        else:
            return "localhost"

    except ValueError as e:
        return "localhost"

def validate_cert_and_key(cert_file_path, key_file_path):
    if not os.path.isfile(cert_file_path):
        raise ValueError(
            f"SSL certificate file '{cert_file_path}' does not exist.")
    if not os.path.isfile(key_file_path):
        raise ValueError(f"SSL key file '{key_file_path}' does not exist.")

    try:
        context = ssl.create_default_context()
        context.load_cert_chain(certfile=cert_file_path, keyfile=key_file_path)
    except ssl.SSLError as e:
        raise ValueError(f"SSL Error: {e}")

    try:
        with open(cert_file_path, 'rb') as cert_file:
            cert_data = cert_file.read()
            cert = x509.load_pem_x509_certificate(cert_data, default_backend())

        if cert.issuer == cert.subject:
            raise ValueError(
                "The certificate is self-signed and not issued by a trusted CA.")

    except Exception as e:
        raise ValueError(f"Certificate verification failed: {e}")

if __name__ == "__main__":
    # Do NOT change workers count for now
    # multi-workers support isn't implemented yet for APScheduler and XRay module

    bind_args = {}

    if UVICORN_SSL_CERTFILE and UVICORN_SSL_KEYFILE:
        validate_cert_and_key(UVICORN_SSL_CERTFILE, UVICORN_SSL_KEYFILE)

        bind_args['ssl_certfile'] = UVICORN_SSL_CERTFILE
        bind_args['ssl_keyfile'] = UVICORN_SSL_KEYFILE

        if UVICORN_UDS:
            bind_args['uds'] = UVICORN_UDS
        else:
            bind_args['host'] = UVICORN_HOST
            bind_args['port'] = UVICORN_PORT

    else:
        if UVICORN_UDS:
            bind_args['uds'] = UVICORN_UDS
        else:

            ip = check_and_modify_ip(UVICORN_HOST)

            logger.warning(f"""
{click.style('IMPORTANT!', blink=True, bold=True, fg="yellow")}
You're running Marzban without specifying {click.style('UVICORN_SSL_CERTFILE', italic=True, fg="magenta")} and {click.style('UVICORN_SSL_KEYFILE', italic=True, fg="magenta")}.
The application will only be accessible through localhost. This means that {click.style('Marzban and subscription URLs will not be accessible externally', bold=True)}.

If you need external access, please provide the SSL files to allow the server to bind to 0.0.0.0. Alternatively, you can run the server on localhost or a Unix socket and use a reverse proxy, such as Nginx or Caddy, to handle SSL termination and provide external access.

If you wish to continue without SSL, you can use SSH port forwarding to access the application from your machine. note that in this case, subscription functionality will not work. 

Use the following command:

{click.style(f'ssh -L {UVICORN_PORT}:localhost:{UVICORN_PORT} user@server', italic=True, fg="cyan")}

Then, navigate to {click.style(f'http://{ip}:{UVICORN_PORT}', bold=True)} on your computer.
            """)

            bind_args['host'] = ip
            bind_args['port'] = UVICORN_PORT

    if DEBUG:
        bind_args['uds'] = None
        bind_args['host'] = '0.0.0.0'

    try:
        uvicorn.run(
            "main:app",
            **bind_args,
            workers=1,
            reload=DEBUG,
            log_level=logging.DEBUG if DEBUG else logging.INFO
        )
    except FileNotFoundError:  # to prevent error on removing unix sock
        pass
M03ED commented 4 weeks ago

if nobody want to test this i can close issue

yaramahmadi commented 4 weeks ago

if nobody want to test this i can close issue

I'll test it and let you know within the next hour.

yaramahmadi commented 4 weeks ago

if nobody want to test this i can close issue

I'll test it and let you know within the next hour.

I used methods 1 and 3, and the issue has been resolved. Thank you!


1. Using Reverse Proxy in Nginx (with HTTPS)

To access the application via HTTPS in Nginx, add the following configuration to your Nginx configuration file:

server {
    listen 80;
    server_name test.domain.com;

    # Redirect HTTP to HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name test.domain.com;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8000;
        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;
    }
}
  1. Replace fullchain.pem and privkey.pem with the paths to your SSL certificates.
  2. Then restart Nginx:

    sudo systemctl restart nginx

Now, HTTP requests will be redirected to https://test.domain.com/dashboard and proxied to port 8000.

2. Using an SSH Tunnel

This method doesn’t require any changes to support HTTPS, and you can temporarily access port 8000 through the tunnel:

ssh -L 8000:localhost:8000 user@server_ip

3. Configuration in Nginx Proxy Manager (with HTTPS)

To add HTTPS in Nginx Proxy Manager:

  1. Log in to Nginx Proxy Manager: Open the panel and navigate to Proxy Hosts. Click on Add Proxy Host.

  2. Initial Settings:

    • Under Domain Names, enter test.domain.com.
    • Set Scheme to http.
    • Set Forward Hostname / IP to 127.0.0.1 and Forward Port to 8000.
  3. Enable SSL:

    • Go to the SSL tab.
    • Enable Enable SSL.
    • Select Force SSL to redirect all HTTP traffic to HTTPS.
    • If using Let’s Encrypt, enable Request a new SSL Certificate and enter the required information to obtain a certificate.
  4. Advanced Settings:

    • Go to the Advanced tab and add the following headers in Custom Nginx Configuration:

      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;
  5. Save Settings: After saving, you can access the application via https://test.domain.com/dashboard.

M03ED commented 4 weeks ago

im happy your problem solved @SegaSh99 what about you ?

MaverickTse commented 1 week ago

I'm having the same problem and method 3 does not work for me. Running NPM and Marzban with Dockge.

Marzban compose file:

services:
  marzban:
    image: gozargah/marzban:latest
    restart: always
    env_file: .env
    network_mode: host
    volumes:
      - ./lib/marzban:/var/lib/marzban
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/stacks/nginx_proxy_manager/letsencrypt/archive:/var/lib/marzban/certs
networks: {}

.env file

UVICORN_PORT = 8443
UVICORN_UDS: "/var/run/docker.socket"
UVICORN_SSL_CERTFILE = "/var/lib/marzban/certs/npm-1/fullchain1.pem"
UVICORN_SSL_KEYFILE = "/var/lib/marzban/certs/npm-1/privkey1.pem"
XRAY_SUBSCRIPTION_URL_PREFIX = https://xui.example.com

NPM setting image

image

image

Tried switching between HTTP and HTTPS but didn't make a difference