Skip to content

Instantly share code, notes, and snippets.

@Akiyamov
Last active March 18, 2025 18:06
Show Gist options
  • Select an option

  • Save Akiyamov/318bfbab9d448cee2d171ee11569f326 to your computer and use it in GitHub Desktop.

Select an option

Save Akiyamov/318bfbab9d448cee2d171ee11569f326 to your computer and use it in GitHub Desktop.

Ноды здесь не рассматриваются, хотя в конце одну команду для них оставлю. Если вы хотите, чтобы API панели торчало в сеть, то делайте это на отдельном поддомене и только с директивой remote_ip в Caddy, мы не хотим лишний раз себя показывать. С отдельным поддоменом для API можно будет вынести подписки и запустить их на отдельном сервере. Если вам это неинтересно, то хватит и двух поддоменов, но всегда лучше все разделить.

В самом начале необходимо создать приложение OAuth в Github. Переходим в https://github.com/settings/developers и создаем новое приложение, где указываем данные следующим образом:

В OAuth также необходимо создать Client secret.

Теперь можно на VPS. Создаем путь /opt/remnawave. Создаем в этой папке docker-compose.yml:

services:
   remnawave-db:
       image: postgres:17
       container_name: 'remnawave-db'
       hostname: remnawave-db
       restart: always
       env_file:
           - .env
       environment:
           - POSTGRES_USER=${POSTGRES_USER}
           - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
           - POSTGRES_DB=${POSTGRES_DB}
           - TZ=UTC
       volumes:
           - remnawave-db-data:/var/lib/postgresql/data
       networks:
           - remnawave-network
       healthcheck:
           test: ['CMD-SHELL', 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}']
           interval: 3s
           timeout: 10s
           retries: 3

   remnawave:
       image: ghcr.io/remnawave/backend:latest
       container_name: 'remnawave'
       hostname: remnawave
       restart: always
       env_file:
           - .env
       networks:
           - remnawave-network

   remnawave-redis:
       image: valkey/valkey:8.0.2-alpine
       container_name: remnawave-redis
       hostname: remnawave-redis
       restart: always
       networks:
         - remnawave-network
       volumes:
         - remnawave-redis-data:/data
       healthcheck:
         test: [ "CMD", "valkey-cli", "ping" ]
         interval: 3s
         timeout: 10s
         retries: 3


   oauth2:
       environment:
           OAUTH2_PROXY_CLIENT_ID: ${OAUTH2_CLIENT_ID}
           OAUTH2_PROXY_CLIENT_SECRET: ${OAUTH2_CLIENT_SECRET}
           OAUTH2_PROXY_COOKIE_SECRET: ${OAUTH2_COOKIE_SECRET}
           OAUTH2_PROXY_GITHUB_USERS: ${OAUTH2_GITHUB_USERS}
           OAUTH2_PROXY_EMAIL_DOMAINS: '*'
           OAUTH2_PROXY_PROVIDER: ${OAUTH2_PROVIDER}
       image: bitnami/oauth2-proxy:latest
       env_file:
           - .env
       container_name: 'oauth2'
       hostname: oauth2
       restart: always
       networks:
           - remnawave-network

   caddy:
       image: caddy:2.9
       container_name: 'caddy'
       hostname: caddy
       restart: always
       ports:
         - 0.0.0.0:443:443
       networks:
           - remnawave-network
       volumes:
           - ./Caddyfile:/etc/caddy/Caddyfile
           - caddy-ssl-data:/data

networks:
   remnawave-network:
       name: remnawave-network
       driver: bridge
       external: false

volumes:
   remnawave-db-data:
       driver: local
       external: false
       name: remnawave-db-data
   remnawave-redis-data:
       driver: local
       external: false
       name: remnawave-redis-data
   caddy-ssl-data:
       driver: local
       external: false
       name: caddy-ssl-data

В этой же папке нужно создать .env:

### APP ###
APP_PORT=3000

DATABASE_URL="postgresql://postgres:postgres@remnawave-db:5432/postgres"

API_INSTANCES=1

REDIS_HOST=remnawave-redis
REDIS_PORT=6379

### JWT ###
### CHANGE DEFAULT VALUES ###
JWT_AUTH_SECRET=CHANGE_ME
JWT_API_TOKENS_SECRET=CHANGE_ME

### TELEGRAM ###
IS_TELEGRAM_ENABLED=false
TELEGRAM_BOT_TOKEN=change_me
TELEGRAM_ADMIN_ID=change_me
NODES_NOTIFY_CHAT_ID=change_me

### FRONT_END ###
FRONT_END_DOMAIN=*

SUB_PUBLIC_DOMAIN=subs.domain.com/api/sub

### SWAGGER ###
SWAGGER_PATH=/docs
SCALAR_PATH=/scalar
IS_DOCS_ENABLED=false

### PROMETHEUS ###
METRICS_USER=admin
METRICS_PASS=admin

### WEBHOOK ###
WEBHOOK_ENABLED=false
### Only https:// is allowed
WEBHOOK_URL=https://webhook.site/1234567890
### This secret is used to sign the webhook payload, must be exact 64 characters. Only a-z, 0-9, A-Z are allowed.
WEBHOOK_SECRET_HEADER=vsmu67Kmg6R8FjIOF1WUY8LWBHie4scdEqrfsKmyf4IAf8dY3nFS0wwYHkhh6ZvQ

### CLOUDFLARE ###
# USED ONLY FOR docker-compose-prod-with-cf.yml
# NOT USED BY THE APP ITSELF
CLOUDFLARE_TOKEN=ey...

### Database ###
### For Postgres Docker container ###
# NOT USED BY THE APP ITSELF
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=postgres

### OAuth2 ###
OAUTH2_CLIENT_ID="CHANGE_ME"
OAUTH2_CLIENT_SECRET="CHANGE_ME"
OAUTH2_COOKIE_SECRET="CHANGE_ME"
OAUTH2_GITHUB_USERS="CHANGE_ME"
OAUTH2_PROVIDER="github"

Для панели нужно создать следующие данные:
JWT_AUTH_SECRET - openssl rand -hex 64;
JWT_API_TOKENS_SECRET - openssl rand -hex 64;
SUB_PUBLIC_DOMAIN - ваш домен для подписок, обязательно в конце /api/sub;
OAUTH2_CLIENT_ID - из OAuth приложения;
OAUTH2_CLIENT_SECRET - из OAuth приложения;
OAUTH2_COOKIE_SECRET - openssl rand -base64 32 | tr -- '+/' '-_';
OAUTH2_PROVIDER - ваш пользователь в Github. Если не знаете какой, то откройте свою страницу и скопируйте из строки, т.е. github.com/Akiyamov это Akiyamov.

Также создаем файл Caddyfile

https://panel.domain.com {
        handle /oauth2/* {
                reverse_proxy oauth2:4180 {
                        header_up X-Real-IP {remote_host}
                        header_up X-Forwarded-Uri {uri}
                }
        }


        handle {
                        forward_auth oauth2:4180 {
                        uri /oauth2/auth
                        header_up X-Real-IP {remote_host}
                        @error status 401
                        handle_response @error {
                                redir * /oauth2/sign_in?rd={scheme}://{host}{uri}
                        }
                }
                reverse_proxy http://remnawave:3000
        }
}
https://subs.domain.com {
        reverse_proxy /api/sub/* http://remnawave:3000
}

Если хотите, чтоб API торчал, то добавляем еще одно:

https://api.domain.com {
        @denied not remote_ip xx.xx.xx.xx
        abort @denied
        reverse_proxy /api/* http://remnawave:3000
}

Вот и все, больше ниче интересного. А, для нод

iptables -I INPUT \! --src айпи_панели -m tcp -p tcp --dport порт_ноды -j DROP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment