it:server:http-reverzni-proxy-server

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
it:server:http-reverzni-proxy-server [2023/01/08 19:53] Petr Nosekit:server:http-reverzni-proxy-server [2025/04/10 16:42] (aktuální) Petr Nosek
Řádek 13: Řádek 13:
  
 <code bash> <code bash>
-sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests+sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests rewrite headers
 sudo systemctl restart apache2 sudo systemctl restart apache2
 </code> </code>
Řádek 75: Řádek 75:
    
  
-==== problém ====+==== problém - Lost Connection.. ====
  
 Problém byl, že u Node REDu apache nefungoval jak má. Po chvíli Node RED vypisoval hlášení: "Lost connection..". Hledal jsem v [[https://discourse.nodered.org/t/node-red-shows-lost-connection-to-server-reconnecting-beacuse-of-websocket-connection-to-wss-comms-api-failed/61220/4|diskusích]] a nenašel jsem uspokojivé řešení, které by fungovalo. Nakonec jsem na podnět v diskusích přešel na nginx - ten byl skutečně řešením.  Problém byl, že u Node REDu apache nefungoval jak má. Po chvíli Node RED vypisoval hlášení: "Lost connection..". Hledal jsem v [[https://discourse.nodered.org/t/node-red-shows-lost-connection-to-server-reconnecting-beacuse-of-websocket-connection-to-wss-comms-api-failed/61220/4|diskusích]] a nenašel jsem uspokojivé řešení, které by fungovalo. Nakonec jsem na podnět v diskusích přešel na nginx - ten byl skutečně řešením. 
  
 +Při testování umělé inteligence chatGPT jsem vznesl dotaz a našla mi řešení pro apache, které se zdá být funkční. Problém je opravdu s web sockety a přidal jsem do konfiguračního souboru toto:
 +
 +<code>
 +RewriteEngine On
 +RewriteCond %{HTTP:Upgrade} =websocket [NC]
 +RewriteRule /(.*)           ws://localhost:1880/$1 [P,L]
 +RewriteCond %{HTTP:Upgrade} !=websocket [NC]
 +RewriteRule /(.*)           http://localhost:1880/$1 [P,L]
 +</code>
 +
 +
 +==== reverzní proxy pro více služeb ====
    
 +S touto konfigurací jsem se natrápil nejvíce. Chtěl jsem, aby jednotlivé služby běžely na těchto url:
 +
 +  * https://192.168.1.20/nodered/
 +  * https://192.168.1.20/portainer
 +
 +Pozor - **je důležité na konci dát vždycky lomítko** - jak v URL, tak konfiguraci, jinak jsem se setkal s problémy a dlouho trvalo, než jsem na toto přišel. Konfigurační soubor apache pak bude obsahovat tyto řádky (počítám s websockety pro nodered):
 +
 +<code>
 +RewriteEngine on
 +
 +RewriteCond %{HTTP:Upgrade} =websocket [NC]
 +RewriteRule ^/nodered/(.*) ws://localhost:1880/$1 [P,L]
 +RewriteCond %{HTTP:Upgrade} !=websocket [NC]
 +RewriteRule ^/nodered/(.*) http://localhost:1880/$1 [P,L]
 +
 +ProxyPass /nodered/ http://localhost:1880/
 +ProxyPassReverse /nodered/ http://localhost:1880/
 +
 +ProxyPass /portainer/ http://localhost:9000/
 +ProxyPassReverse /portainer/ http://localhost:9000/
 +
 +</code>
 +
 +
 +
 +==== úpravy pro Nextcloudpi ====
 +
 +Nejprve jsem do konfiguračního souboru Apache zadal tyto řádky:
 +
 +<code>
 +RewriteRule ^/nextcloud/(.*) ws://localhost:8880/$1 [P,L]  
 +RewriteRule ^/nextcloud/(.*) http://localhost:8880/$1 [P,L]
 +</code>
 +
 +Poté je podle [[https://docs.nextcloud.com/server/20/admin_manual/configuration_server/reverse_proxy_configuration.html|návodu k nextcloudu]] nutné editovat soubor **config.php** a nastavit v něm reverzní proxy. V mém případě jsem musel zadat něco takového:
 +
 +<code php>
 +'trusted_proxies' =>
 +array (
 +  11 => '127.0.0.1',
 +  12 => '::1',
 +  13 => 'e906aaab10d6',
 +  14 => '172.27.0.3',
 +  15 => '192.168.1.20'
 +),
 +'overwriteprotocol' => 'https',
 +'overwritehost' => 'mojedomena.cz',
 +'overwritewebroot'  => '/nextcloud',
 +'overwritecondaddr' => '^192\.168\.1\.20$'
 +</code>
 +
 +
 +**Bohužel jsem zjistil, že konfigurace nebyla dostačující.** Webové rozhraní fungovalo, ale když jsem se snažil použít klienta na automatickou synchronizaci, tak klient měl problém s https protokolem. Prozatím jsem hledání řešení vzdal, protože jsem ani po několika hodinách nebyl úspěšný.
 +
 +
 +==== PiHole ====
 +
 +Pro konfiguraci Pi Hole bylo nutné do Apache zadat tyto řádky:
 +
 +<code>
 +ProxyPass /pihole/ http://localhost:8089/admin/       
 +ProxyPassReverse /pihole/ http://localhost:8089/admin/
 +</code>
 +
 +
 +Stejně služba nefungovala jak má, protože se mi nevypisovala uložená data. Pak jsem narazil na tuto diskusi s řešením: https://www.reddit.com/r/Actualfixes/comments/ulzrbj/fix_pihole_behind_proxy_error_invalid_json/
 +
 +Řešení popisuje, že je potřeba přizpůsobit nastavení lighttpd v docker kontejneru. V docker konterjneru přidat do souboru ///etc/lightttpd/external.conf// tento řádek (nastavit tam IP adresu serveru):
 +
 +<code>
 +setenv.add-environment = ( "VIRTUAL_HOST" => "<your-domain>" )
 +</code>
 +
 +Řešení bude funkční pouze do chvíle aktualizaci kontejneru. Proto jsem do docker compose souboru přidal tento řádek:
 +
 +<code>
 +volumes:
 +  - /mojecesta/external.conf:/etc/lighttpd/external.conf
 +</code>
 +
 +Nejprve ale bylo potřeba na disku vytvořit soubor /mojecesta/external.conf jinak se mi nepodařilo kontejner spustit.
 +
 +
 +Pak jsem ale našel lepší řešení v [[https://github.com/pi-hole/docker-pi-hole#environment-variables|dokumentaci docker Pi Hole kontejneru]]. Výsledná konfigurace pro docker-compose pak vypadá takto:
 +
 +<code yaml>
 +pihole:
 +  container_name: pihole
 +  image: pihole/pihole:latest
 +  ports:
 +  - "8089:80/tcp"
 +  - "53:53/tcp"
 +  - "53:53/udp"
 +  - "67:67/udp"
 +  environment:
 +  - TZ=Etc/UTC
 +  - WEBPASSWORD=supertajneheslo
 +  - INTERFACE=eth0
 +  - VIRTUAL_HOST=192.168.1.20
 +  volumes:
 +  - ./volumes/pihole/etc-pihole:/etc/pihole
 +  - ./volumes/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
 +    #- ./volumes/pihole/external.conf:/etc/lighttpd/external.conf
 +  dns:
 +  - 127.0.0.1
 +  - 1.1.1.1
 +  cap_add:
 +  - NET_ADMIN
 +  restart: unless-stopped
 +
 +</code>
 +
 +V závěru jsem objevil ještě jeden problém. Pi Hole po přihlášení přesměrovává na IP_ADRESA_SERVER/admin . Takže po přihlášení do Pi Hole jsem přesměrován mimo reverzní proxy. Nakonec jsem to vyřešil tak, že jsem Pi Hole spustil na IP_ADRESA_SERVER/admin namísto /pihole. Funkční konfigurace Apache pak vypadá takto:
 +
 +<code>
 +RewriteRule ^(.*)/pihole/$ $1/admin/ [R]
 +ProxyPass /admin/ http://localhost:8089/admin/
 +ProxyPassReverse /admin/ http://localhost:8089/admin/
 +</code>
 +
 +
 +Setkal jsem se s problémem, když jsem pihole nemohl nastartovat, protože port 53 byl obsazený již nějakou jinou službou. V mém případě to byl connect manager. Pomohla editace souboru **/etc/connman.prefs** (v distribuci OSMC je soubor tady **/etc/osmc/prefs.d/connman**) a nastavit:
 +
 +<code>
 +dnsproxy=no
 +</code>
 +
 +A pak restartovat connection managera: 
 +
 +<code bash>
 +systemctl restart connman
 +</code>
 +
 +
 +Další tipy k samotnému Pi Hole:
 +
 +{{youtube>62j2UB3No3E?}}
 +
 +A tady odkaz na servery s blocklisty:
 +
 +  * https://avoidthehack.com/best-pihole-blocklists
 +  * https://firebog.net/
 +
 +
 +==== Redmine ====
 +
 +Potřeboval jsem nasadit Redmine pomocí Dockeru. Databáze MySQL běží na hostitelském počítači také v Dockeru, ale naslouchá pouze na `127.0.0.1`. Aby se Redmine mohl připojit k databázi, použil jsem nástroj `socat`, který přeposílá porty. Apache běží také jako kontejner a slouží jako reverzní proxy.
 +
 +=== Konfigurace Redmine kontejneru ===
 +
 +Vytvořil jsem následující `docker-compose.yml`:
 +
 +<code yaml>
 +redmine:                                                                                  
 +    container_name: redmine                                                               
 +    image: redmine                                                                        
 +    restart: always                                                                       
 +    ports:                                                                                
 +      - '127.0.0.1:3000:3000'                                                             
 +    environment:                                                                                                                           
 +      REDMINE_DB_MYSQL: 172.17.0.1                                                        
 +      REDMINE_DB_PORT: 33060                                                              
 +      REDMINE_DB_USERNAME: db-user                                         
 +      REDMINE_DB_PASSWORD: db-password                                               
 +      REDMINE_DB_DATABASE: db-name                                             
 +      REDMINE_SECRET_KEY_BASE: secret-key                                        
 +    volumes:                                                                              
 +      - './volumes/redmine/configuration.yml:/usr/src/redmine/config/configuration.yml' 
 +</code>
 +
 +Redmine se připojuje na IP `172.17.0.1`, což je adresa hostitelského systému z pohledu Dockeru. Jelikož databáze naslouchá pouze na `127.0.0.1`, bylo nutné vytvořit TCP forward pomocí `socat`.
 +
 +=== Socat pro přesměrování TCP portu ===
 +
 +Použil jsem službu `systemd`, která při startu systému spustí `socat`:
 +
 +<code ini>
 +/etc/systemd/system/mysql-forward-docker.service
 +
 +[Unit]
 +Description=MySQL TCP forwarder for Docker
 +After=network-online.target docker.service
 +Wants=network-online.target docker.service
 +
 +[Service]
 +ExecStartPre=/bin/bash -c 'until /usr/bin/socat -T1 -u TCP-LISTEN:0,bind=172.17.0.1 - > /dev/null & PID=$!; sleep 1; kill $PID; do echo "Waiting for 172.17.0.1 to become bindable..."; sleep 2; done'
 +ExecStart=/usr/bin/socat TCP-LISTEN:33060,bind=172.17.0.1,fork TCP:127.0.0.1:3306
 +Restart=on-failure
 +RestartSec=3
 +
 +[Install]
 +WantedBy=multi-user.target
 +</code>
 +
 +Tento skript vytvoří forward: všechny požadavky na `172.17.0.1:33060` jsou přeposílány na `127.0.0.1:3306`. Tímto způsobem se Redmine kontejner dostane k databázi, která běží na hostiteli.
 +
 +* `socat` slouží jako jednoduchý TCP forwarder.
 +* Využívá `fork`, takže zvládne více spojení najednou.
 +* Před spuštěním hlavního příkazu čeká, než bude možné IP `172.17.0.1` bindnout.
 +
 +=== MySQL uživatel a přístup ===
 +
 +Při vytváření uživatele v MySQL jsem musel explicitně uvést IP adresu `127.0.0.1`. Pokud bych použil `localhost`, spojení by nefungovalo.
 +
 +Například:
 +
 +<code sql>
 +CREATE USER 'db-user'@'127.0.0.1' IDENTIFIED BY 'db-password';
 +GRANT ALL PRIVILEGES ON db-name.* TO 'db-user'@'127.0.0.1';
 +</code>
 +
 +=== Nastavení firewallu ===
 +
 +Redmine běží v jiné Docker síti a má vlastní IP adresu. V mém případě to byla `172.19.0.2`. Aby se kontejner mohl připojit na port 33060, bylo třeba povolit tento provoz ve firewallu:
 +
 +<code bash>
 +ufw allow from 172.19.0.2/16 to any port 33060
 +</code>
 +
 +IP adresu kontejneru lze zjistit příkazem:
 +
 +<code bash>
 +docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redmine
 +</code>
 +
 +Tímto jsem zajistil funkční připojení Redmine k databázi běžící na hostitelském systému.
 +
 +
 +=== Nastavení Apache ===
 +
 +Jelikož Redmine běží v Dockeru na portu `127.0.0.1:3000`, bylo potřeba nakonfigurovat reverzní proxy přes Apache. Apache běží také jako kontejner a naslouchá na portu 80 a 443.
 +
 +Použil jsem následující konfiguraci virtuálních hostů v Apache:
 +
 +<code apache>
 +<VirtualHost *:80>
 +    ServerName redmine.example.com
 +    ServerAlias redmine.example.com
 +
 +    ServerAdmin info@example.com
 +    Redirect permanent "/" "https://redmine.example.com/"
 +</VirtualHost>
 +
 +<IfModule mod_ssl.c>
 +    <VirtualHost _default_:443>
 +
 +        ServerName redmine.example.com
 +        ServerAlias redmine.example.com
 +        ServerAdmin info@example.com
 +
 +        Protocols h2 http/1.1
 +
 +        # Reverse proxy konfigurace
 +        ProxyPreserveHost On
 +        ProxyPass / http://localhost:3000/
 +        ProxyPassReverse / http://localhost:3000/
 +
 +        # SSL konfigurace
 +        SSLEngine on
 +
 +        SSLCertificateFile      /var/lib/dehydrated/certs/example.com/cert.pem
 +        SSLCertificateKeyFile   /var/lib/dehydrated/certs/example.com/privkey.pem
 +        SSLCertificateChainFile /var/lib/dehydrated/certs/example.com/chain.pem
 +        SSLCACertificateFile    /var/lib/dehydrated/certs/example.com/fullchain.pem
 +
 +    </VirtualHost>
 +</IfModule>
 +</code>
 +
 +Tato konfigurace:
 +
 +  * Přesměrovává HTTP požadavky na HTTPS.
 +  * Používá SSL certifikáty vystavené nástrojem [dehydrated](https://github.com/dehydrated-io/dehydrated).
 +  * Pomocí `ProxyPass` a `ProxyPassReverse` přesměrovává provoz na Redmine běžící na `localhost:3000`.
 +  * `ProxyPreserveHost On` zajišťuje, že hlavička `Host` zůstane zachována, což je důležité pro aplikace, které ji používají.
 +
 +Tímto způsobem lze přistupovat k Redmine z prohlížeče pomocí domény `https://redmine.example.com/`.
 +
 +
  
  
Řádek 182: Řádek 473:
 </code> </code>
  
- 
-===== limit, který jsem nevyřešil ===== 
- 
-Pokud máme doménu, tak je to všechno v pořádku. Každou službu můžeme zařadit pod subdoménu. V mém případě tedy Node RED běží pod doménou garmin.cn a portainer pod portainer.garmin.cn.  
- 
-Problém ovšem nastává, když jsem v lokální síti a nevyužívám lokální [[it:iot:hodinky-garmin-api-call|dns]]. V tu chvíli chci volat pouze IP adresu a za ni lomítkem určit službu. Tedy například: 192.168.1.20/portainer. A to se mi právě nepodařilo vyřešit.  
- 
-Jedna služba přes reverzní proxy obsadí IP adresu: 192.168.1.20 a už není možné pracovat se složkama alá 192.168.1.20/portainer, protože to už se snaží obsluhovat Node RED. 
  • it/server/http-reverzni-proxy-server.1673207608.txt.gz
  • Poslední úprava: 2023/01/08 19:53
  • autor: Petr Nosek