itzg / docker-rcon-web-admin

A Docker image that runs rcon-web-admin
MIT License
85 stars 17 forks source link

Unable to use behind proxy. #2

Open therealeldaria opened 5 years ago

therealeldaria commented 5 years ago

I'm using the Docker-compose but modified so that the ports are not exposed, I did not want to expose the ports on the network unencrypted, so I set up a nginx proxy with letsencrypt. On the proxy I send traffic from port 443 to http://dockername:4326 I can get to the admin page with no issues but it does not seem to want to connect to the socket. I have a suspicion that the actual webbrowser attempts to connect instead of internal in the docker container. Is there a way to configure it to connect internally or do I need to expose the port outside the continer?

itzg commented 5 years ago

When you add a new server in "Server Management" can you make sure in "Server Host" you are giving the docker-compose service name of the minecraft-server container? With my example compose file, the hostname minecraft is coming from here.

therealeldaria commented 5 years ago

Problem is that I can't get to the Server Management Page, it just keeps loading, showing three dots, pulsating. I can see the menu by clicking the 3 lines at the left, and I see the sub-menus, Dashboard, Server Management, Widgets, etc. But none of them loads, except those that link here, and to paypal.

itzg commented 5 years ago

Gotcha. I’ll try recreating that proxy setup too and see if I can debug it.

therealeldaria commented 5 years ago

Docker-compose.yml:

  rcon:
     container_name: rcon
     image: itzg/rcon
     volumes:
       - "rcon:/opt/rcon-web-admin/db"
   nginx_proxy:
     container_name: nginx_proxy
     image: nginx
     ports:
       - "80:80"
       - "443:443"
     volumes:
       - "/home/user/mc/docker-nginx/html:/usr/share/nginx/html"
       - "/etc/letsencrypt:/etc/letsencrypt:ro"
       - "/home/user/mc/docker-nginx/default.conf:/etc/nginx/conf.d/default.conf"

 volumes:
   rcon

nginx configuration (default.conf)

server {
    listen 80;
    return 301 https://$host$request_uri;
}

upstream rcon {
    server rcon:4326;
    keepalive 32;
}

server {
    listen 443 ssl http2 default_server;
    server_name  minecraft.myserver.net;

    root /usr/share/www;
    index  index.html index.htm;

    client_max_body_size 0;

    ssl_certificate /etc/letsencrypt/live/minecraft.myserver.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/minecraft.myserver.net/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    ssl_prefer_server_ciphers on;

    location / {
      proxy_pass http://rcon/;
      proxy_http_version 1.1;
      proxy_set_header Connection "upgrade";
      proxy_set_header Upgrade $http_upgrade;
    }
}
emmett421 commented 5 years ago

Did you ever figure this out? I'm having the same exact issue except I'm using traefik as my proxy.

itzg commented 5 years ago

I think I accidentally ran into the same kind of issue when I forgot to expose the websocket port. That led me to find this issue and solution description in the upstream:

https://github.com/brainfoolong/rcon-web-admin/issues/9

zeigerpuppy commented 4 years ago

did anyone solve this for the use of nginx?

quodos commented 4 years ago

Unfortunately the link to the solution is down as the maintainer of the original rcon-web-admin repo changed.

I figure you have to set the RWA_WEBSOCKET_URL or RWA_WEBSOCKET_URL_SSL variable to a path and then proxy it to the port via nginx. Unfortunately setting RWA_WEBSOCKET_URL_SSL as environment variable seems to have no effect as the tool still tries to access the websocket via ws://...:4327.

itzg commented 4 years ago

Thanks for pointing that out @quodos . Apparently I missed a couple of links that need to point at the new location.

itzg commented 4 years ago

@quodos , I got the links fixed. As for the core issue you will need to contact the maintainers over there, but they are quite responsive now.

fraserkyle commented 3 years ago

I have resolve this by creating separate nginx configs. 1 for the WebUI and the other for WebSockets.

In my docker compose: RWA_WEBSOCKET_URL_SSL: "wss://ws.{my rcon url}" RWA_WEBSOCKET_URL: "ws://ws.{my rcon url}"

/etc/nginx/conf.d/{my rcon url}.conf `
map $http_upgrade $connection_upgrade { default upgrade; '' close; }

server { server_name {my rcon url};

location / {
  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_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection $connection_upgrade;
  proxy_set_header Host $host; 

  proxy_read_timeout  90;

  proxy_pass http://{my INTERNAL rcon url}:4326;
}

} `

/etc/nginx/conf.d/ws.{my rcon url}.conf `
map $http_upgrade $connection_upgrade { default upgrade; '' close; }

server { server_name ws.{my rcon url};

location / {
  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_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection $connection_upgrade;
  proxy_set_header Host $host; 

  proxy_read_timeout  90;

  proxy_pass http://{my INTERNAL rcon url}:4327;
}

} `

you can then use certbot to generate your sll certificates

jippi commented 3 years ago

I ended up with this nginx configuration to make it work

map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
}

map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

server {
    listen              443 ssl http2;
    listen              [::]:443 ssl http2;

    server_name        __YOUR_HOSTNAME__;

    ssl_certificate     /etc/letsencrypt/live/__YOUR_HOSTNAME__/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/__YOUR_HOSTNAME__/privkey.pem;
    ssl_session_timeout 5m;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:MEDIUM:!SSLv2:!PSK:!SRP:!ADH:!AECDH;
    ssl_prefer_server_ciphers on;

    location /ws/ {
        proxy_pass http://127.0.0.1:4327/;
        gzip on;

        # Websocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_redirect     off;

        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 $proxy_x_forwarded_proto;
        proxy_set_header X-Frame-Options SAMEORIGIN;
        proxy_set_header X-Forwarded-Ssl on;
    }

    location / {
        proxy_pass http://127.0.0.1:4326;
        gzip on;

        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 $proxy_x_forwarded_proto;
        proxy_set_header X-Frame-Options SAMEORIGIN;
        proxy_set_header X-Forwarded-Ssl on;
    }
}

and my docker-compose (mostly from the tutorials)

services:
  minecraft:
    image: itzg/minecraft-server
    ports:
      - "25565:25565"
      - "28016:28016"
    volumes:
      - "/data/minecraft/data:/data"
    environment:
      EULA: "TRUE"
      ENABLE_RCON: "true"
      RCON_PASSWORD: "__REPLACE_THIS__"
      RCON_PORT: 28016
      # enable env variable replacement
      REPLACE_ENV_VARIABLES: "TRUE"
      # define an optional prefix for your env variables you want to replace
      ENV_VARIABLE_PREFIX: "CFG_"
      # and here are the actual variables
      CFG_DB_HOST: "http://localhost:3306"
      CFG_DB_NAME: "minecraft"
      CFG_DB_PASSWORD_FILE: "/run/secrets/db_password"
      WHITELIST: __REPLACE_THIS__
      OPS: __REPLACE_THIS__
      ANNOUNCE_PLAYER_ACHIEVEMENTS: "true"
    restart: always

  rcon:
    image: itzg/rcon
    environment:
      RWA_ENV: "true"
      RWA_USERNAME: "__REPLACE_THIS__"
      RWA_PASSWORD: "__REPLACE_THIS__"
      RWA_ADMIN: "true"
      RWA_RCON_HOST: "minecraft"
      RWA_RCON_PORT: "28016"
      RWA_WEB_RCON: "true"
      RWA_WEBSOCKET_URL_SSL: "wss://__YOUR_HOSTNAME__/ws"
      RWA_WEBSCOCKET_URL: "wss://__YOUR_HOSTNAME__/ws"
    links:
      - minecraft
    ports:
      - "4326:4326"
      - "4327:4327"
    volumes:
      - "/data/minecraft/rcon:/opt/rcon-web-admin/db"

secrets:
  db_password:
    file: ./db_password
codestation commented 1 year ago

@elriti For traefik i used this:

  rcon:
    image: itzg/rcon
    volumes:
      - rcon_data:/opt/rcon-web-admin/db
    environment:
      RWA_ENV: "TRUE"
      RWA_USERNAME: admin
      RWA_PASSWORD: admin
      RWA_ADMIN: "TRUE"
      RWA_RCON_HOST: minecraft
      RWA_RCON_PORT: 28016
      RWA_WEBSOCKET_URL_SSL: "wss://rcon.example.com/ws"
      RWA_WEBSOCKET_URL: "ws://rcon.example.com/ws"
      # needs to match the password configured for the container, which is 'minecraft' by default
      RWA_RCON_PASSWORD: minecraft
    networks:
      - gateway
      - minecraft
    deploy:
      placement:
        constraints:
          - node.hostname == myhost
      labels:
        - traefik.enable=true
        - traefik.http.services.rcon-web.loadbalancer.server.port=4326
        - traefik.http.services.rcon-ws.loadbalancer.server.port=4327

        - traefik.http.routers.rcon-web.rule=Host(`rcon.example.com`)
        - traefik.http.routers.rcon-web.service=rcon-web
        - traefik.http.routers.rcon-web.entryPoints=https
        - traefik.http.routers.rcon-web.tls=true
        - traefik.http.routers.rcon-web.tls.certresolver=tls

        - traefik.http.routers.rcon-ws.rule=Host(`rcon.example.com`) && Path(`/ws`)
        - traefik.http.routers.rcon-ws.service=rcon-ws
        - traefik.http.routers.rcon-ws.entryPoints=https
        - traefik.http.routers.rcon-ws.tls=true
        - traefik.http.routers.rcon-ws.tls.certresolver=tls

Basically i created an alternate route so my host + /ws (exact path) goes to the port 4327 of my service. No need for an extra subdomain.

DoTheEvo commented 1 year ago

For caddy reverse proxy

add env variables to the docker-compose.yml or to the .env file

RWA_WEBSOCKET_URL: "ws://rcon.example.com/ws" RWA_WEBSOCKET_URL_SSL: "wss://rcon.example.com/ws"

and in Caddyfile add this, minecraft-rcon is a pingable hostname of the docker container

rcon.example.com {
        reverse_proxy /ws minecraft-rcon:4327
        reverse_proxy minecraft-rcon:4326
}
philipt4 commented 1 year ago

@codestation Do you have two rcon containers running? What is happening with the load balancing there isnt completely clear to me.

I'd appreciate any pointers here. Using Traefik wildcard ssl reverse proxy (the labels I use work with all other of my web apps) and unmodified/default minecraft server config which runs properly,

version: "3"

services:
  mc:
    image: itzg/minecraft-server:latest
    container_name: "mc"
    environment:
      EULA: TRUE
      VERSION: 1.19.2
      OVERRIDE_SERVER_PROPERTIES: TRUE
      ENABLE_RCON: TRUE
      RCON_PASSWORD: minecraft
    ports:
      - 25565:25565/tcp
    networks:
      - "proxy"
    # tty: true
    # stdin_open: true
    restart: unless-stopped
    volumes:
      - ./minecraft-data:/data

  mc-dash:
    image: itzg/rcon:latest
    container_name: "mc-dash"
    environment:
      RWA_ENV: TRUE
      RWA_WEB_RCON: TRUE
      RWA_USERNAME: admin
      RWA_PASSWORD: admin
      RWA_ADMIN: TRUE
      # is referring to the hostname of 'mc' compose service below
      RWA_RCON_HOST: minecraft
      # needs to match the password configured for the container, which is 'minecraft' by default
      RWA_RCON_PASSWORD: minecraft
      RWA_RCON_PORT: "25575"
      RWA_WEBSOCKET_URL_SSL: "wss://mc-dash.mydomain.com:4327"
    ports:
      - 4326:4326
      - 4327:4327
    restart: unless-stopped
    networks:
      - "proxy"
    volumes:
      - ./rcon_data:/opt/rcon-web-admin/db
    labels:
      traefik.enable: "true"
      traefik.http.services.mc-dash.loadbalancer.server.port: "4326"
      traefik.http.routers.mc-dash.entrypoints: "web"
      traefik.http.routers.mc-dash.rule: "Host(mc-dash.mydomain.com)"
      traefik.http.middlewares.mc-dash-https-redirect.redirectscheme.scheme: "https"
      traefik.http.routers.mc-dash.middlewares: "mc-dash-https-redirect"
      traefik.http.routers.mc-dash-secure.entrypoints: "websecure"
      traefik.http.routers.mc-dash-secure.rule: "Host(mc-dash.mydomain.com)"
      traefik.http.routers.mc-dash-secure.tls: "true"
      traefik.http.routers.mc-dash-secure.service: "mc-dash"
      traefik.docker.network: "proxy"

networks:
  proxy:
    external: true

mc-dash.mydomain.com is accessible, but is blank as seemingly the backend/ws isnt functioning. No 'mc-dash'/rcon web errors in console.

codestation commented 1 year ago

Do you have two rcon containers running?

@philipt4 no, only one. The container uses a volume to store their data so i don't think that it can work with multiple replicas.

For your config, the rcon container expect the string TRUE instead of a boolean value, so make sure to quote the value (TRUE is different from 'TRUE' in yaml). Also the RWA_RCON_HOST value must match the service name (mc in your case). Also for some reason, if RWA_WEB_RCON is set then the rcon client won't connect (dunno why), so i had to remove it.

I grabbed your compose file and made rcon work with this config:

version: "3"

services:
  mc:
    image: itzg/minecraft-server:latest
    container_name: "mc"
    environment:
      EULA: TRUE
      VERSION: 1.19.2
      OVERRIDE_SERVER_PROPERTIES: TRUE
      ENABLE_RCON: TRUE
      RCON_PASSWORD: minecraft
    ports:
      - 25565:25565/tcp
    networks:
      - "proxy"
    # tty: true
    # stdin_open: true
    restart: unless-stopped
    volumes:
      - ./minecraft-data:/data

  mc-dash:
    image: itzg/rcon:latest
    container_name: "mc-dash"
    environment:
      RWA_ENV: 'TRUE'
      #RWA_WEB_RCON: 'TRUE'
      RWA_USERNAME: admin
      RWA_PASSWORD: admin
      RWA_ADMIN: 'TRUE'
      # is referring to the hostname of 'mc' compose service below
      RWA_RCON_HOST: mc
      # needs to match the password configured for the container, which is 'minecraft' by default
      RWA_RCON_PASSWORD: minecraft
      RWA_RCON_PORT: "25575"
      RWA_WEBSOCKET_URL_SSL: "wss://mc-dash.mydomain.com:4327"
    ports:
      - 4326:4326
      - 4327:4327
    restart: unless-stopped
    networks:
      - "proxy"
    volumes:
      - ./rcon_data:/opt/rcon-web-admin/db

networks:
  proxy:
    external: true

Didn't check your traefik config, just connected to http://localhost:4326/

philipt4 commented 1 year ago

@codestation I appreciate the response! Your above compose file worked well for running on my localhost. To allow the same config to go hand in hand with traefik, I had to add the additional fields:

For environment, I modified RWA_WEBSOCKET_URL_SSL and added RWA_WEBSOCKET_URL:

    environment:
      RWA_WEBSOCKET_URL_SSL: "wss://mc-dash.mydomain.com/ws"
      RWA_WEBSOCKET_URL: "ws://mc-dash.mydomain.com/ws"

For labels, I added:

    labels:
      traefik.enable: "true"
      traefik.http.services.mc-dash-web.loadbalancer.server.port: "4326"
      traefik.http.services.mc-dash-ws.loadbalancer.server.port: "4327"
      traefik.http.middlewares.mc-dash-https-redirect.redirectscheme.scheme: "https"

      traefik.http.routers.mc-dash-web.rule: "Host(`mc-dash.mydomain.com`)"
      traefik.http.routers.mc-dash-web.service: "mc-dash-web"
      traefik.http.routers.mc-dash-web.entrypoints: "websecure"
      traefik.http.routers.mc-dash-web.tls: "true"

      traefik.http.routers.mc-dash-ws.rule: "Host(`mc-dash.mydomain.com`) && Path(`/ws`)"
      traefik.http.routers.mc-dash-ws.service: "mc-dash-ws"
      traefik.http.routers.mc-dash-ws.entrypoints: "websecure"
      traefik.http.routers.mc-dash-ws.tls: "true"

      traefik.docker.network: "proxy"

For anyone that Is looking at this thread with the same issue, those were the only added fields added/modified on top of the config from codestation's most recent comment. Traefik + Wildcard cert on my end + docker rcon working here. EDIT: some people use for their 'entrypoint' traefik label have it set to 'http' and 'https' (such as codestation in his first comment on this thread). I use 'web' and 'websecure'.

toddejohnson commented 1 month ago

It looks like merging the ports has been a PR since 2020 https://github.com/rcon-web-admin/rcon-web-admin/pull/17

Is this upstream project dead upstream? No commits since 2020.

itzg commented 1 month ago

Is this upstream project dead upstream? No commits since 2020.

Yes, it seems to be, which compromises my ability to maintain the image of it.

aziran07 commented 2 weeks ago

Do you have two rcon containers running?

@philipt4 no, only one. The container uses a volume to store their data so i don't think that it can work with multiple replicas.

For your config, the rcon container expect the string TRUE instead of a boolean value, so make sure to quote the value (TRUE is different from 'TRUE' in yaml). Also the RWA_RCON_HOST value must match the service name (mc in your case). Also for some reason, if RWA_WEB_RCON is set then the rcon client won't connect (dunno why), so i had to remove it.

Looking at rcon.js in the original repository (https://github.com/rcon-web-admin/rcon-web-admin/blob/4a8b04a0d4bfaf248b2c7259d2882c93794f5e7e/src/rcon.js#L123), processing when RWA_RCON_WEB is true and false is different. (This is probably to distinguish between games that support web rcon and games that do not.) This option is only applied when the image is first built, so it must be set to false when the image is first created - if you use this image for minecraft.